Taking Enterprise Java to a New Level

Java EE 6: A Better Development Experience Awaits! - Part 2

    

New Specifications

At this point we will introduce some of the specifications that are brand new to this release. With so much to say and so little space to say it in we can only give a taste of some of the added features of these specifications, but it should be enough to make the improvements obvious. We will not go into JASPIC because it is strictly a Service Provider Interface (SPI) for internal use within the container, and we won't discuss interceptors because they existed in the previous release as part of the EJB specification and are therefore not really new.

RESTful Web Services

Because JAX-RS existed in 1.0 form before being included in Java EE 6 it had already become fairly widely adopted. Adding the 1.1 version to Java EE 6 gave it an enterprise blessing and ensured an integration with other Java EE components.

The simplicity of REST makes it an attractive alternative to SOAP-based protocols and also enables an existing enterprise application to easily export parts of itself as web services. A few annotations and a simple configuration model unite to create an almost effortless service creation experience. Listing 1 shows part of a root resource class for a RESTful web service.

The @Path annotation specifies the URI that directs a request to be serviced by this resource class. The URI is always relative to the server and can contain any number of variable names, each enclosed by curly braces and separated by slashes. For example, the path in Listing 1 is specified as /employee/{id}, meaning that a request with a URI of the form http://someserver.com/employeeApp/someContextRoot/employee/24513 may be serviced by this resource class. The last URI component will get assigned to the id variable as a result of the @PathParam injection, which in this example occurs in the constructor.

The @GET annotation denotes the HTTP method that is to be responded to. There are annotations for each of the other HTTP methods as well. @Produces matches the request with the service method that returns the corresponding return type, and @QueryParam injects the value of the named query parameter into the target. A URI of http://someserver.com/employeeApp/someContextRoot/employee/24513?count=5 would cause the size method parameter to be injected with the value 5 in our example.

RESTful web services are a much simpler way to achieve interoperability across systems than traditional XML-based web services, and this has led to REST becoming more and more popular. The JAX-RS standard provides the simplest possible model for developers to be able to leverage REST, while still staying within a familiar and standard programming model.

Managed Beans

A managed bean is really just a generic managed class that can be used virtually anywhere in the container. It is as simple as a JavaBean, but can be adorned with annotations to cause additional services to be supplied by the container, including resource injection, lifecycle callbacks and interception. Their container-wide applicability means they can be both injected into an EJB and act as a traditional JSF managed bean. They can also be an injection target for CDI, but more on that later.

An example of a managed bean can be quite trivial indeed, with nothing more than a class annotated with @Managed-Bean. The @Resource annotation can be used to inject resources. The lifecycle annotations, such as @PostConstruct, will be recognized by the container to cause the appropriate callback method invocations to occur. Interception annotations, as defined by the Interceptors specification, may even be applied to trigger interceptors. An example of a managed bean is in Listing 2.

Contexts and Dependency Injection

In Java EE 5 a fairly limited form of resource injection was available using @Resource and a few other specific annotations for certain resource types. The dependency injection state-of-the-art had gone far beyond that point, however, so an advanced form of injection was created. Contexts and Dependency Injection (CDI) defines a set of injection rules combined with a well-defined lifecycle for objects bound to contexts and ends up providing not only qualifiable injection but event notification, interception and decoration. We won't go into all of the features of CDI, but a couple of examples show how easy and powerful injection has become.

The Dependency Injection for Java specification defined a set of standard annotations that can be used by injection frameworks and containers. CDI supports two of those annotations for developers to use on their domain code and two meta-annotations to decorate their own annotations for their injection infrastructure:

@Inject – specifies an injection point

@Qualifier – meta-annotation used to denote an annotation that will further constrain injection points

@Scope – meta-annotation used when defining a new scope

@Named – a built-in qualifier annotation for naming a bean

Because of the integration with the rest of Java EE, CDI can both inject, and inject into, managed beans (in JSF or not) and EJBs. It can also inject into servlets. The contexts can correspond to any of the three Request, Session and Application scopes in servlets, as well as a new Conversation scope in JSF. A unique user-defined scope can be added if needed.

A qualifier is an annotation that is typically defined by the application developer and can be used at an injection point to provide more details about the object to inject. It provides semantics to the injection, but decouples the actual injection point from the code or logic that dictates what gets injected. Listing 3 shows an example of using qualified injection. The @Preferred qualifier is defined and then qualifies the injection for the Customer object to be a WebCustomer. Because CustomerOrder is scoped to the HTTP session (being annotated with the built-in @SessionScoped annotation) the same contextual CustomerOrder stateful session bean instance will be injected and referenced everywhere within the current session. The life cycle of the stateful session bean will be controlled and managed by CDI.

Much more is possible with CDI so some experimentation or going through a tutorial is highly recommended. See the Java EE tutorial for a good starting point.

Bean Validation

Validation of state is a reasonably common task that can happen at almost any layer in an application. Sometimes it is even performed at multiple layers, for example at the presentation layer and again at the backend persistence engine. In order to prevent duplication, and to enable practical and versatile validation of domain object state, the bean validation standard was created. Validation can be performed through the use of a set of standard annotations and APIs, and a compliant pluggable validation provider that implements the specification.

Setting a bean up to be validated is as easy as putting constraint annotations on the bean fields (or properties) to be checked. They can be placed on a class for validation to occur against the entire class, but most times it makes sense just to validate individual state fields. The validation will occur either programmatically by invoking a validation API or as a result of a lifecycle state change in a JSF or JPA application. If a bean fails validation then the validator will throw a ValidationException indicating that the bean is invalid in its current state.

Developers can additionally define their own constraints and validation logic, enabling validation to take any form or to perform almost any checking. The result is that validation can be as simple or as complex as you want or need it to be, with additional flexibility to create groups of constraints to be validated at specific times. Listing 4 shows a class decorated with some of the built-in constraints, along with a custom @ValidScore constraint. The constraint definition (with its three required attributes) and the validation implementation class are also shown.

The HockeyGame class was left as a simple class to keep it clear of other artifacts unrelated to validation, but it would likely be an entity that was annotated as such and contained JPA mappings. Instances could be validated at the time they are created, or further down the stack at database insertion time. When being validated, the ScoreValidator.isValid() method will be invoked against the ScoringInfo instance stored in the game.

Summary

The Java EE 6 platform is a complete multi-vendor Java platform, and the fact that it is based on standards means it can used by more developers and more applications. Although Java as a language has had more and more features added to it, sometimes adding its share of complexity to the programming experience, the enterprise platform has become easier and easier to use with each new release. More is available and less is required on the part of vendors and developers. At the same time, Java EE has retained its reputation as being a stable and reliable platform for consultants and corporate IT departments alike.

We have tried to give you an idea of the kinds of features that have been added to Java EE 6, but much has been left unsaid. The best way to get a more accurate feel for the platform is to download it and try it out. The Glassfish Reference Implementation server is open source and free and can be used both for experimenting and for deploying applications into production. See [4] for more information about how to download and get started with Glassfish. A better development experience awaits!

Mike Keith
Mike Keith

What do you think?

JAX Magazine - 2014 - 03 Exclucively for iPad users JAX Magazine on Android

Comments

Latest opinions