Quantcast
Channel: RealDolmen Experts » Java EE
Viewing all articles
Browse latest Browse all 3

Devoxx 2013: Java EE 7

$
0
0

At Devoxx 2013, the tracks that I was most interested in were the Java SE and Java EE tracks, specifically in presentations about the new stuff in Java SE 8 and Java EE 7.
In this post, I’ll talk about the new features of Java EE 7.

As I already mentioned in my previous blog post, I attended 2 sessions on Java EE 7 this year. One by Java EE evangelists Arun Gupta and Antonio Goncalves during the University days and one by David Delabassee during the Conference. All of them gave a good overview on the new and updated specifications.

I’ll give you a broad overview on what Java EE 7 is all about and what it can mean for your day-to-day work.

History

First, I’ll explain the history of Java EE to describe where the platform is coming from:

JavaEE_Future

It all started with Java EE 1.2 and 1.3 where the basic specifications were implemented: Servlet, JSP, EJB with CMP in Java EE 1.3 and JMS. Java EE 1.4 focused on web services development. Java EE 1.4 and older weren’t the most popular versions with Java developers. They were difficult, bloated and a lot of boilerplate code and XML configuration was necessary to implement the tiniest feature.
Java EE 5 made a complete 180° turn. Its focus was put on ease of development. The platform had to be easier in use and more fun to develop with. They succeeded!
Annotations were added to enable light-weight configuration of the application, much of the XML configuration was made redundant. EJB 3.0 was created, a much improved version of EJB 2.x. That specification was also used as a basis for new web services development. To simplify persistence, JPA emerged, a standardized version of popular ORM frameworks.
Java EE 6 made the platform even more configurable by introducting CDI, a standardized Contexts and Dependency Injection API. It fully implemented Restful Web Services and created a Java EE 6 Web Profile to enable light-weight fully managed web application development.

Because an image says more than a thousand words, Java EE 7 is all about these 3 big themes:

javaee7-theme

I’ll discuss these themes when I talk about the different specifications.

Specifications

Java EE 7 includes many updated and some new specifications:

javaee7-pancake

CDI 1.1

CDI is now integrated into most Java EE specifications like JPA, EJB, Bean Validation, EventListeners etc. In the past, some specifications like EJB 3.x had their own dependency injection mechanism. In EJB 3.x you would use the @EJB annotation to inject EJB’s. Now you can also use CDI for that.

CDI is enabled by default. A beans.xml file is not necessary anymore, unless you want to override the new bean-discovery-mode option or other convention over configuration. The bean-discovery-mode option describes which beans will be discovered and injected automatically. You can specify the following values:

  • all: All types in the archive will be considered for discovery and injection.
  • annotated: Only types with bean defining annotations in the archive will be considered.
  • none: No beans in the archive will be considered.

You can use a new annotation: @Vetoed. Beans annotated with @Vetoed will not be discovered nor injected, regardless of the bean-discovery-mode configuration. It can be enabled on a per class basis, or for an entire package by annotating a package-info.java file.

Bean Validation 1.1

Bean Validation is integrated into more Java EE specifications like JAX-RS and JAXB. It’s not yet integrated into the SOAP API’s. You can also use Bean Validation in Java SE if you include the necessary Bean Validation provider on the classpath.

Bean Validation supports standardized method-level validation. You annotate pre- and post conditions on constructors, methods and method parameters. This promotes “programming by contract”.

@AssertTrue
public boolean validate (@NotNull CreditCard creditCard) {
    // Details ommitted
}

Talking about a cohesive integrated platform, CDI can now be used in Validator classes to inject dependencies.

Interceptors 1.2

Interceptors are also integrated into most Java EE specifications, except in the SOAP API’s.

New is the fact that you can associate interceptors with the instantiation of a class. You probably already know that the @AroundInvoke annotation exists. Now you can annotate methods with @AroundConstruct to perform certain functionality before and after a new instance of a class is created.

@AroundConstruct
public void validateConstructor(InvocationContext context) {
    System.out.println(
        "MyAroundConstructInterceptor.validateConstructor");
}

Interceptor ordering is supported. You can define interceptor priority using the @Priority annotation. Use the following values in descending priority order and add your own integer value to them to order your interceptors: PLATFORM_BEFORE, LIBRARY_BEFORE, APPLICATION, LIBRARY_AFTER and PLATFORM_AFTER

Concurrency Utilities 1.0

In the past, creating your own threads in a Java EE managed application was prohibited. The container took care of concurrency. You shouldn’t intervene in that or you could open the box of concurrency pandora.
Now Java EE 7 supports creating container managed threads yourself. You can use a ManagedExecutorService, ManagedScheduledExecutorService or ManagedThreadFactory for that. The executor or factory needs a Runnable or Callable instance as a parameter.

@Resource(name = "DefaultManagedExecutorService")
ManagedExecutorService executor;

public boolean doSomething() throws InterruptedException {
    TestStatus.latch = new CountDownLatch(1);
    executor.submit(new Runnable() {
        @Override
        public void run() {
            // Details ommitted
        }
    });
    TestStatus.latch.await(2000, TimeUnit.MILLISECONDS);
    return true;
}

JPA 2.1

Schema generation has been standardized in Java EE 7. You can set the javax.persistence.schema-generation.database.action option in persistence.xml. Valid values are none, create, drop-and-create and drop. A validate or update setting doesn’t seem to exist (yet). Other options like loading data using SQL scripts are also standardized.

You can define additional indexes for schema generation in your code using the @Index annotation.

@Entity
@Table(indexes = {
        @Index(columnList = "ISBN"),
        @Index(columnList = "NBOFPAGE")
})
public class Book {
    // Details ommitted
}

An unsynchronized persistence context is available now. When you use this type of persistence context, your changes are not flushed to the database until joinTransaction() is invoked. This way, you have more control of when the flush to the database occurs.

@PersistenceContext(
    synchronization = SynchronizationType.UNSYNCHRONIZED)
EntityManager em;

public void persistWithoutJoin(Employee e) {
    em.persist(e);
}

public void persistWithJoin(Employee e) {
    em.joinTransaction();
    em.persist(e);
}

Stored procedures can be specified in a standardized way using the @NamedStoredProcedureQuery annotation.

@NamedStoredProcedureQuery(name="PersonStoredProcedure",
    procedureName="PERSON_SP")

In the presentation, no code was shown on how to call the stored procedure as far as I remember. In his examples on GitHub, Arun mentions “TBD: how to invoke StoredProcedure”. But on http://www.mastertheboss.com/quickstart-tutorials-hibernate/jpa/jpa-21-tutorial I found some code on how to call a named stored procedure that needs parameters.

StoredProcedureQuery spq = EntityManager
    .createNamedStoredProcedureQuery("PersonStoredProcedure");
spq.registerStoredProcedureParameter(1, String.class,
    ParameterMode.INOUT);
spq.setParameter(1, "FRANK");
spq.registerStoredProcedureParameter(2, Integer.class,
    ParameterMode.IN);
spq.setParameter(2, 100);

spq.execute();
String response = spq.getOutputParameterValue(1);

JTA 1.2

Transactional services that were used in EJB’s are now extracted to the JTA specification.
You can define transaction management on managed beans as CDI interceptor binding using the @Transactional annotation which seems to be coming straight out of Spring. You can specify on which exceptions the transaction should be rolled back, and which exceptions shouldn’t cause a rollback.

@Transactional(value = Transactional.TxType.REQUIRED,
    rollbackOn = {SQLException.class, JMSException.class},
    dontRollbackOn = SQLWarning.class)
public class BookRestService {
    // Details ommitted
}

You can also define a managed bean as transaction scoped. The bean will only live during the scope of one transaction. Just annotate the bean with @TransactionScoped.

EJB 3.2

As discussed above, a lot of EJB specific services like EJB dependency injection and transaction management, were extracted to other existing specifications.

EJB 3.2 contains numerous updates and improvements.
Now lifecycle callback methods can opt-in to be transactional whereas before transaction management was mostly ignored on lifecycle callbacks.

@Stateful
public class HelloBean {
    @PersistenceContext(type=PersistenceContextType.EXTENDED)
    private EntityManager em;

    @TransactionAttribute(
                TransactionAttributeType.REQUIRES_NEW)
    @PostConstruct
    public void init() {
        myEntity = em.find(...);
    }

    @TransactionAttribute(
                TransactionAttributeType.REQUIRES_NEW)
    @PostConstruct
    public void destroy() {
        em.flush();
    }
}

You can disable the passivation of stateful beans using the annotation @Stateful(passivationCapable = false). In some cases this can increase performance, scalability and robustness.

EJB 3.x Lite is a light-weight version of the full EJB 3.x API.
It supports EJB development, but doesn’t contain MDB’s, remoting or JAX-WS / JAX-RPC service endpoints. EJB 3.1 Lite didn’t contain asynchronous session beans nor timer services.
Now in EJB 3.2 Lite, local asynchronous invocations and a non-persistent EJB Timer Service are included. You can define an asynchronous method by annotating it with @Asynchronous. Timer Service methods can be scheduled using the annotation @Scheduled. You can use some kind of cron expression to define the scheduling.

@Schedule(hour = "*", minute = "*", second = "*/5",
    info = "Every 5 second timer")
public void printDate() {
    // Details ommitted
}

JMS 2.0

Java EE 7 brings you a complete JMS API overhaul. The programming model is extremely simplified.

The JMSContext API now supports a Builder Pattern style of programming.
Several JMS interfaces implement AutoCloseable so they can be used in try-with-resources blocks. And you can now define JMS Connection Factories and Destinations like queues and topics with annotations. You can find the comparison between the JMS 1.1 and JMS 2.0 API’s below.

public void sendMessageJMS11(
        ConnectionFactory connectionFactory,
        Queue queue, String text) {
    try {
        Connection connection =
            connectionFactory.createConnection();
        try {
            Session session = connection.createSession(
                false,Session.AUTO_ACKNOWLEDGE);
            MessageProducer messageProducer =
                session.createProducer(queue);
            TextMessage textMessage =
                session.createTextMessage(text);
            messageProducer.send(textMessage);
        } finally {
            connection.close();
        }
    } catch (JMSException ex) {
        // handle exception (details omitted)
    }
}

 

@Inject
JMSContext context;

@Resource(mappedName =
    Resources.SYNC_CONTAINER_MANAGED_QUEUE)
Queue queue;

public void sendMessageJMS20(String text) {
    try (JMSContext context =
            connectionFactory.createContext();) {
        context.createProducer().send(queue, text);
    } catch (JMSRuntimeException ex) {
        // handle exception (details omitted)
    }
}

 

@JMSDestinationDefinition(
    name = Resources.SYNC_CONTAINER_MANAGED_QUEUE,
    resourceAdapter = "jmsra",
    interfaceName = "javax.jms.Queue",
    destinationName = "syncContainerManagedQueue",
    description = "My Sync Queue")

Servlet 3.1

Servlet 3.1 supports non-blocking I/O. You can use this when processing large data sets in servlets. Several methods were added to existing interfaces and new interfaces were introduced: ReadListener and WriteListener. You can only use this in asynchronous servlets.

AsyncContext context = request.startAsync();
ServletInputStream input = request.getInputStream();
input.setReadListener(new MyReadListener(input, context));

You can build richer protocols on top of HTTP by using the Servlet 3.1 protocol upgrade feature. This protocol upgrade is what HTML5 WebSockets use under the hood. A new HttpUpgradeHandler interface was created for this purpose.

By using the <deny-uncovered-http-methods /> tag in the application’s web.xml you can improve security of your applications. It does exactly what it says, deny all HTTP method requests for methods that aren’t covered in web.xml.

WebSocket 1.0

WebSockets are at the basis of HTML5. They enable full-duplex bi-directional communication over a single TCP connection. A good example of websocket usage is a chat client where several clients can post to and read messages of each other.

The client and server endpoints can be annotated.

@ServerEndpoint("/chat")
public class ChatEndpoint {
    @OnMessage
    public void message(String message, Session client)
            throws IOException, EncodeException {
        for (Session peer : client.getOpenSessions()) {
            peer.getBasicRemote().sendText(message);
        }
    }
}

You can declare them programmatically as well by extending the Endpoint class. By extending the EndpointConfig classes ClientEndpointConfig or ServerEndpointConfig, you can modify your endpoint configuration.
You also have different lifecycle callbacks like @OnOpen, @OnClose and @OnError at your disposal.

You have the ability to create your own encoders and decoders of messages. I can best explain this with an example.

@ServerEndpoint(value = "/encoder",
    encoders = {MyMessageEncoder.class},
    decoders = {MyMessageDecoder.class})
public class MyEndpoint {
    @OnMessage
    public MyMessage messageReceived(MyMessage message) {
        System.out.println("messageReceived: " + message);
        return message;
    }
}

 

public class MyMessageEncoder
        implements Encoder.Text<MyMessage> {
    @Override
    public String encode(MyMessage myMessage)
            throws EncodeException {
        return myMessage.getJsonObject().toString();
    }

    @Override
    public void init(EndpointConfig ec) { }

    @Override
    public void destroy() { }
}

 

public class MyMessageDecoder
    implements Decoder.Text<MyMessage> {
    @Override
    public MyMessage decode(String string)
            throws DecodeException {
        MyMessage myMessage = new MyMessage(
            Json.createReader(new StringReader(string)).
                                        readObject());
        return myMessage;
    }

    @Override
    public boolean willDecode(String string) {
        return true;
    }

    @Override
    public void init(EndpointConfig ec) { }

    @Override
    public void destroy() { }
}

EL 3.0

Historically, Expression Language has been bundled under the JSP specification. Now that part is extracted to a separate updated specification. This way, you can use EL in a stand-alone environment to:

  • Evaluate EL expressions
  • Get/set bean properties
  • Define a static method as an EL function
  • Define an object instance as an EL name
ELProcessor elp = new ELProcessor();
elp.defineBean("employee", new Employee("Charlie Brown"));
String name = elp.eval("employee.name");

JSF 2.2

In JSF you now have a standardized version of Spring web-flow: Faces Flow!
You can define reusable flows in a XML and package them in a JAR. You can also build flows using annotations and a FlowBuilder. As you can see in the example below, you can use flows and @FlowScoped beans in EL. @FlowScoped beans only live during – as the annotation implies – the flow they were created in.

@Produces @FlowDefinition
public Flow defineFlow(
        @FlowBuilderParameter FlowBuilder flowBuilder) {
    String flowId = "flow1";
    flowBuilder.id("", flowId);
    flowBuilder.viewNode(flowId, "/" + flowId + "/"
        + flowId + ".xhtml").markAsStartNode();
    flowBuilder.returnNode("taskFlowReturn1").
        fromOutcome("#{flow1Bean.returnValue}");
    flowBuilder.returnNode("goHome").
        fromOutcome("#{flow1Bean.homeValue}");
    flowBuilder.inboundParameter("param1FromFlow2",
        "#{flowScope.param1Value}");
    flowBuilder.inboundParameter("param2FromFlow2",
        "#{flowScope.param2Value}");
    flowBuilder.flowCallNode("call2").
        flowReference("", "flow2").
        outboundParameter("param1FromFlow1",
            "param1 flow1 value").
        outboundParameter("param2FromFlow1";,
            "param2 flow1 value");

    return flowBuilder.getFlow();
}

You can create reusable skins and themes using Resource Library Contracts.
JSF 2.2 now has better support for HTML pass-through attributes for HTML5-friendly markup and contains a File Upload component.

JAX-RS 2.0

Like the JMS 2.0 API, the JAX-RS 2.0 API brings you a more simplified programming model, using the Builder Pattern to invoke REST services.
You can also have asynchronous clients and servers. Restful clients work with Futures, restful servers work with suspended async responses.

Future<String> future = ClientBuilder.newClient()
    .target("http://www.foo.com/book")
    .request()
    .async()
    .get(String.class);
try {
    String body = future.get(1, TimeUnit.MINUTES);
} catch (InterruptedException | ExecutionException e) {
    // Details ommitted
}

 

@Path("/async")
public class AsyncResource {
    @GET
    public void asyncGet(@Suspended AsyncResponse asyncResp) {
        new Thread(new Runnable() {

            public void run() {
                String result = veryExpensiveOperation();
                asyncResp.resume(result);
            }

        }).start();
    }
}

You can process request and response headers by using message filters. New interfaces were created for this purpose: ClientRequestFilter, ClientResponseFilter, ContainerRequestFilter and ContainerResponseFilter. In a ClientRequestFilter implementation for example, you process the ClientRequestContext parameter to the filter() method.

Entity interceptors (not for JPA entities but JAX-RS messages!) can be used to marshal and unmarshal HTTP message bodies. For that, you have to implement the ReaderInterceptor.aroundReadFrom() and WriterInterceptor.aroundWriteTo() interface methods that take a ReaderInterceptorContext or WriterInterceptorContext respectively.

JSON-P 1.0

JSON-P is the JSON counterpart of JAXP that processes XML. You can use the new Streaming API for creating and parsing JSON. The Streaming API supports a Builder Pattern and is similar to the StAX API for XML processing.

With the JSON ObjectBuilder you create a JsonObject model in memory by adding elements.

JsonObject jsonObject = Json.createObjectBuilder()
        .add("title", "The Matrix")
        .add("year", 1999)
        .add("cast", Json.createArrayBuilder()
                .add("Keanu Reaves")
                .add("Laurence Fishburne")
               .add("Carrie-Anne Moss"))
        .build();

The JsonParser is an event-based parser that reads JSON data from a stream.

public void testSimpleObject() throws JSONException {
    JsonParser parser = Json.createParser(Thread
        .currentThread()
        .getContextClassLoader()
        .getResourceAsStream("/2.json"));

    assertEquals(JsonParser.Event.START_OBJECT, parser.next();
    assertEquals(JsonParser.Event.KEY_NAME, parser.next());
    assertEquals(JsonParser.Event.VALUE_STRING, parser.next();
    assertEquals(JsonParser.Event.KEY_NAME, parser.next());
    assertEquals(JsonParser.Event.VALUE_STRING, parser.next();
    assertEquals(JsonParser.Event.END_OBJECT, parser.next());
}

Batch Applications 1.0

In batch applications, two styles of processing exist: chunk-style processing and batchlet-style processing.
Chunk-style processing is item-oriented. You process a batch of items at a time. A batch job contains one or more steps. A step contains chunks where a certain amount of items are processed. Every chunk is processed in a separate transaction. An ItemReader reads an item for the chunk that needs to be processed. An ItemProcessor processes the item that was read. At the end of the batch or the chunk, an ItemWriter writes the results to where you want them to go: a file, an e-mail, the database, … Abstract implementations already exist for these interfaces.
Batchlet-style processing is task-oriented. It doesn’t process items but does one specific task, like sending an e-mail. It is also part of a step. Your batchlet implementation class has to implement the Batchlet interface.

You can write listeners around specific phases of jobs, steps or chunks. You have to implement specific interfaces, or extend their respective abstract classes. The relevant interfaces are:

  • JobListener
  • StepListener
  • ChunkListener
  • ItemRead/Write/ProcessListener
  • SkipRead/Write/ProcessListener
  • RetryRead/Write/ProcessListener

The job definition is specified in an XML file. You can create partitions declaratively in XML or programmatically in Java to run job parts in parallel.
In the XML you can define the complete workflow. A flow consists of elements that execute together as a unit. You can define splits that support concurrent execution of several flows. In the XML you can also create decision paths to allow conditional continuation of the batch. For the XML decision, you have to write an implementation of the Decider interface that makes the decision and returns a String that refers to the path that needs to be followed.
An example of an XML job definition is this:

<job id="myJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        version="1.0">
    <step id="step1" next="decider1">
        <batchlet ref="myBatchlet1"/>
    </step>
    <decision id="decider1" ref="myDecider">
        <next on="foobar" to="step3"/>
        <stop on="foobar2" exit-status="foobar3"
            restart="step3"/>
    </decision>
    <step id="step2">
        <batchlet ref="myBatchlet2"/>
    </step>
    <step id="step3">
        <batchlet ref="myBatchlet3"/>
    </step>
</job>

Here you have a small example on how to launch a batch job and print out some information about it:

out.println("About to start the job");
JobOperator jo = BatchRuntime.getJobOperator();
out.println("Got the job operator: " + jo);
long jid = jo.start("myJob", new Properties());
out.println("Job submitted: " + jid);
out.println(jo.getJobInstanceCOUNT("myJob") as Computed
    + " job instance found");
JobExecution je = jo.getJobExecution(jid);
out.println("Job created on: " + je.getCreateTime());
out.println("Job started on: " + je.getStartTime());
out.println("Found: " + jo.getJobNames().size() + " jobs");
for (String j : jo.getJobNames()) {
    out.println("--> " + j);
}

A point of interest is that batch processing also works outside of the container.

JavaMail 1.5

A MailSession can now be defined using annotations.

@MailSessionDefinition(name = "java:comp/myMailSession",
    host = "smtp.gmail.com",
    transportProtocol = "smtps",
    properties = {
        "mail.debug=true"
    })
public class AnnotatedEmailServlet extends HttpServlet {
    @Resource(lookup = "java:comp/myMailSession")
    Session session;

    // Details ommitted
}

JCA 1.7

In the Java Connector Architecture, you can also define objects using the annotations @ConnectionDefinition and @AdministeredObjectDefinition.

@AdministeredObjectDefinition(
    className="MyQueueImpl.class"
    name="java:comp/MyQueue"
    resourceAdapter="myAdapter")

General

Over the entire platform, Java EE 7 now supports default resources, such as a default datasource, a default JMS factory etc. If you don’t specify a resource name for injection, the default resource will be injected.

@Resource(lookup="java:comp/DefaultDataSource")
DataSource myDS;
// is the same as
@Resource
DataSource myDS;

All Sun-related namespaces are changed to xmlns.jcp.org and older specifications like EJB Entity Beans (CMP, BMP, EJB QL), JAX-RPC and JAXR are pruned from the new specification.

The Future

Of course, the Java world doesn’t end at Java EE 7. They are already looking forward to Java EE 8 for quite some time now. In Java EE 8, the focus will be on leveraging the platform in the cloud, standardizing PaaS to make cloud applications portable over different cloud providers. The specification leads will also continue to improve the platform and update it for HTML5, caching, NoSQL, polyglot programming and other trending topics.

Summary

As you have seen, a lot of new features were added to Java EE 7 that makes the platform more productive, easier to develop with and more future proof.
I hope you now have an overview on the new features of Java EE 7 so you can start looking around for some more information and try out the examples and the platform yourself.

I hope you enjoyed reading this blog post and that you have learned something new from it. Please be so kind to give your constructive feedback and comments below.

Before closing off, I would like to refer to the following sources where I took the liberty of getting the images and examples from:


Viewing all articles
Browse latest Browse all 3

Trending Articles