Adam Bien's Weblog

The Hidden JavaEE 7 Gem - Lambdas With JDK 1.7

EL 3.0 (Expression Language 3.0) JSR-341 is part of JSF, JSP and so a JavaEE 7 and comes with amazing capabilities. You can pass objects to the ELProcessor to access the properties, define collection literals or perform computations:


import java.util.Map;
import java.util.Set;
import javax.el.ELProcessor;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;

public class ELTest {

    private ELProcessor cut;

    @Before
    public void init() {
        this.cut = new ELProcessor();
    }

    @Test
    public void formula() {
        Long result = (Long) this.cut.eval("2*2");
        assertThat(result, is(4l));
    }

    @Test
    public void bean() {
        Workshop workshop = new Workshop("javaee airhacks");
        this.cut.defineBean("workshop", workshop);
        String title = (String) this.cut.eval("workshop.title");
        assertThat(title, is(workshop.getTitle()));
    }

    @Test
    public void listLiteral() {
        String listLiteral = "{1,2,3}";
        Set list = (Set) this.cut.eval(listLiteral);
        assertFalse(list.isEmpty());
        System.out.println("List: " + list);
    }

    @Test
    public void mapLiteral() {
        String listLiteral = "{\"one\":1,\"two\":2,\"three\":3}";
        Map map = (Map) this.cut.eval(listLiteral);
        assertFalse(map.isEmpty());
        System.out.println("Map: " + map);
    }
    
}

Also EL 3.0 allows you to declare and execute lambdas …on Java 7:


    @Test
    public void lambda(){
        Object result = this.cut.eval("[1,2,3,4,5,6,7,8].stream().
							filter(i->i%2 == 0).map(i->i*10).toList()");
        assertNotNull(result);
        System.out.println("Result: " + result);
        result = this.cut.eval("[1,5,3,7,4,2,8].stream().sorted((i,j)->j-i).toList()");
        System.out.println("Result: " + result);
    }


ELProcessor can be started outside the application server within JavaSE environment. You only need a single maven dependency:

<dependency>
	<groupId>org.glassfish</groupId>
	<artifactId>javax.el</artifactId>
	<version>3.0.0</version>
</dependency>

The code above is an example used during the airhacks.com.

See you at Java EE Workshops at MUC Airport!


NEW workshop: Microservices with Java EE 7 and Java 8, January 26th, 2015, Airport Munich

A book about rethinking Java EE Patterns

Comments:

In formula(), you're asserting that 2*2 = 41

Posted by Robert J Saulnier on September 13, 2013 at 05:32 PM CEST #

Yes, this is indeed a gem. I'd say an undocumented gem.

In JSF, you can do some crazy stuff with this. Expanding on your example, look at this:

<h:form prependId="false">
<p><h:inputText id="index" value="#{requestScope.i}" /></p>

<!--
#{xx = (null != requestScope.i) ? requestScope.i : 0}
-->

<p id="output"><h:outputText value="#{[1,2,3,4,5,6,7,8].stream().
filter(i->i%2 == 0).map(i->i*10).toArray()[xx]}" /></p>
<h:commandButton value="submit" />
</h:form>

Now, it would be better to put that "xx" assignment in an <h:outputText rendered="false"> so it doesn't show up in the page, but, hey, putting it in a comment reminds us of the bad old days of scriptlets.

Posted by Ed Burns on September 14, 2013 at 03:47 PM CEST #

The only Problem i got is:
Strings, Strings, Strings

That's why i'm not the biggest Fan of ExpressionLanguage - It's all just a String, no Type-Safety at Compile-Time, poor Refactoring-Support etc.

Posted by Gustav on September 16, 2013 at 11:38 AM CEST #

@Robert,

"In formula(), you're asserting that 2*2 = 41"

This would be a hidden miracle, not a gem :-)

I'm asserting a long. So it is 4 + the l character and not the one number.

Thanks for scanning the code!,

adam

Posted by Adam Bien on September 16, 2013 at 03:31 PM CEST #

@Gustav,

it is not type safe, what makes it usable for an entire new set of use cases. It is another option for the "Fluid Logic" pattern:

http://www.adam-bien.com/roller/abien/entry/restful_calculator_with_javascript_and

With Java you would have to implement a custom DSL with e.g. ANTLR to achieve similar effect.

thanks for your opinion!,

adam

Posted by Adam Bien on September 16, 2013 at 03:33 PM CEST #

WTF! Collection literals and lambda expressions in EL! And available in Java 7 too!!!

I wonder if collection literals will make into Java 9, since it's weird to have them en EL and not in Java itself. I would love to write

[1,2,3,4,5,6,7,8].stream().filter(i->i%2 == 0).map(i->i*10).toList();

in Java!

Does anybody here has the power to make it happen? :-)

Posted by ikk on September 28, 2013 at 06:04 AM CEST #

Post a Comment:
  • HTML Syntax: NOT allowed
realworldpatterns.com
...the last 150 posts
...the last 10 comments
License