Friday, January 22, 2010

Contexts and Dependency Injection for Java EE (CDI) - Part 2


Custom Object Factories with CDI Producers/Disposers
In a majority of cases, @Inject and @Qualifier annotations gives the container static control over object creation. However, there are cases where it makes a lot of sense for you to control object creation and destruction yourself in Java code. Good examples are complex object creation/destruction, legacy/third-party API integration, objects that need to be constructed dynamically at runtime and creating injectable strings, collections, numeric values and so on. Along the same lines as the traditional object factory pattern, this is what CDI producers and disposers allow you to do. Another way of looking at this is that the container allows you to step in and take manual control over creating/destroying objects when it makes sense.

In the following code, we'll show you how to create a simple abstraction over the low-level JMS API using CDI producers and disposers. As you might already know, plain JMS code can be pretty verbose because the API is so general purpose. Using CDI, we can create a custom JMS object factory that hides most of the verbose code to handle the JMS connection and session, keeping the actual JMS API client code pretty clean.
@Stateless
public class OrderService {
@Inject @OrderSession private Session session;
@Inject @OrderMessageProducer private MessageProducer producer;

public void sendOrder(Order order) {
try {
ObjectMessage message = session.createObjectMessage();
message.setObject(order);
producer.send(message);
} catch (JMSException e) {
e.printStackTrace();
}
}
}

Rather than injecting the JMS connection factory and queue, we are instead actually injecting the JMS session and message producer, using qualifiers specific to messaging for orders (@OrderSession, @MessageProducer). The session and message producer is being injected from a shared object factory with a set of CDI producers and disposers handling the JMS session, connection and message producer life-cycle behind the scenes.

Here is the code for the custom object factory:
public class OrderJmsResourceFactory {
@Resource(name="jms/ConnectionFactory")
private ConnectionFactory connectionFactory;

@Resource(name="jms/OrderQueue")
private Queue orderQueue;

@Produces @OrderConnection
public Connection createOrderConnection() throws JMSException {
return connectionFactory.createConnection();
}

public void closeOrderConnection (
@Disposes @OrderConnection Connection connection)
throws JMSException {
connection.close();
}

@Produces @OrderSession
public Session createOrderSession (
@OrderConnection Connection connection) throws JMSException {
return connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
}

public void closeOrderSession(
@Disposes @OrderSession Session session) throws JMSException {
session.close();
}

@Produces @OrderMessageProducer
public MessageProducer createOrderMessageProducer(
@OrderSession Session session) throws JMSException {
return session.createProducer(orderQueue);
}

public void closeOrderMessageProducer(
@Disposes @OrderMessageProducer MessageProducer producer)
throws JMSException {
producer.close();
}
}

The underlying order queue and connection factory is being injected into the JMS object factory via the Java EE 5 @Resource annotation. The methods annotated with @Produces are producer methods. The return values of these methods are made available for injection. When needed, you can apply qualifiers, scopes, names and stereotypes to these return values by applying annotations to the producer methods. In our example, we are applying the @OrderConnection, @OrderSession and @OrderMessageProducer qualifiers to the injectable JMS connections, sessions and message producers we are programmatically constructing. The produced objects belong to the default dependent scope.

Very interestingly, you should note that producer methods can request injected objects themselves through their method parameters. For example, when the container creates an order session by invoking the createOrderSession method, it sees that the method needs a JMS connection qualified with the @OrderConnection qualifier. It then resolves this dependency by invoking the createOrderConnection producer method. The createOrderMessageProducer producer method is similarly dependent on the createOrderSession producer.

On the other side of the equation any method with a parameter decorated with the @Disposes annotation signifies a disposer. In the example, we have three disposers disposing of JMS connections, sessions and message producers qualified with the @OrderConnection, @OrderSession and @OrderMessageProducer qualifiers. Just as producer methods are called into action as the objects they produce are needed, the disposer associated with an object is called when the object goes out of scope. For the interest of readability, all disposers must belong in the same bean as their matching producer methods.

Having covered some of the mechanical syntax details, let's now take a step back and look at the example from a functional standpoint. When the order service needs the injected order session and message producer, the associated producer methods are invoked by CDI. In the course of creating the session and message producer, CDI also creates the JMS connection, since it is a declared dependency for the producer methods. The producer methods utilize the underlying queue and connection factory injected into our JMS object factory as needed. All these injected objects are then cleaned up properly when they go out of scope.

This example should demonstrate to you how the relatively simple concept of producers and disposers can be combined in innovative and powerful ways when you need it.

Custom Scopes and Resource Factories
Think about the implications of the example above. Because the JMS resources are in the dependent scope, they are tied to the life-cycle of the order service EJB. The service is a stateless session bean that is discarded from the object pool when not in use, along with the injected JMS resources. Now imagine that the service is a singleton or application scoped managed bean instead and is thus very long lived. This means that this code would cause the container to create and inject open connections/sessions that are not released for a while, potentially causing performance problems. Can you think of a way to solve this problem?

Hint: one way to solve this is to use a custom @TransactionScoped or @ThreadScoped for the JMS resources. This is being considered for addition to the Resin container (as such, it is probably a good optimization even for the EJB case). Also under consideration: Adding generic JMS/JDBC abstractions based on CDI similar to the example as part of Resin that you can simply use out-of-the-box. Can you imagine how the JDBC abstraction might look like? Would it be useful to you?

CDI producers and disposers support even more powerful constructs such as utilizing injection point meta-data, using producer fields, or using producers with Java EE resources and so on - you should check out the CDI specification for details (alternatively, feel free to check out the Weld reference guide that's a little more reader-friendly). Utilizing producers and scoped beans with JSF is particularly interesting and we will look at this in a later article focusing on CDI's interaction with JSF.

To give you a taste of some of the more advanced features, let's look at a producer example using injection point meta-data. By using injection point meta-data in producers, you can get runtime information about where the object you are programmatically creating will be getting injected into. You can use this data in very interesting ways in your code. Here is an example that constructs and injects a custom logger into a service:

@Stateless
public class BidService {
@Inject private Logger logger;
...
}

public class LoggerFactory {
@Produces
public Logger getLogger(InjectionPoint injectionPoint) {
return Logger.getLogger(
injectionPoint.getMember().getDeclaringClass().getSimpleName());
}
}

As you can see from the example above, all you need to do to get access to injection point meta-data is include the InjectionPoint interface as a producer method parameter. When CDI invokes your producer, it will collect meta-data at the injection point (the logger instance variable in this case) and pass it to your producer. The injection point interface can tell you about the bean being injected, the member being injected, qualifiers applied at the injection point, the Java type at the injection point, any annotations applied and so on. In the example, we are creating a logger specific to the class that holds the logger using the name of the class that is the injection target.

The injection point interface is actually part of the CDI SPI geared toward portable extensions, which we will discuss in a later article.

OpenWebBeans Portable Extensions
One of the goals of the Apache CDI implementation, OpenWebBeans, is to expose various popular Apache projects as CDI portable extensions. It's very likely you will see something similar to the logger example above as a CDI portable extension for Log4J (CDI portable extensions for Apache commons is probably very likely too).

Naming Objects
As we discussed, one of the primary characteristics of CDI is that dependency injection is completely type-safe and not dependent on character-based names that are prone to mistyping and cannot be checked via an IDE, for example. While this is great in Java code, beans would not be resolvable without a character-based name outside Java such as in JSP or Facelet markup. CDI bean name resolution in JSP or Facelets is done via EL. By default, CDI beans are not assigned any names and so are not resolvable via EL binding. To assign a bean a name, it must be annotated with @Named like so:

@RequestScoped @Named
public class Bid {
...
}

The default name of the bean is assigned to be "bid" - CamelCase with the first letter lower-cased. The bean would now be resolvable via EL binding as below:

<h:inputText id="amount" value="#{bid.amount}"/>

Similarly, objects created by producer methods are assigned the name of the method or the Java property name by default when the producer is annotated via @Named. The list of products produced in the example below is named "products", for instance:
@Produces @ApplicationScoped @Named
public List getProducts() { ... }
You can most certainly override default names as needed as shown below:
@Produces @ApplicationScoped @Catalog @Named("catalog")
public List getProducts() { ... }

@ConversationScoped @Named("cart")
public class ShoppingCart {

In most cases, you would likely not override bean names, unless overriding names improves readability in the context of JSP/Facelet EL binding.

Names in Dependency Injection
Technically, @Named is defined to be a qualifier by JSR 330. This means that you can use character-based names to resolve dependencies in JSR 299 if you really, really want to. However, this is discouraged in CDI and there are few good reasons to do it instead of using more type-safe Java based qualifiers (can you think of what the reasons might be?).

Looking up CDI Beans
While dependency injection is the way to go most of the time, there are some cases where you cannot rely on it. For example, you may not know the bean type/qualifier until runtime, it may be that there are simply are no beans that match a given bean type/qualifier or you may want to iterate over the beans which match a certain bean type/qualifier. The powerful CDI Instance construct allows for programmatic bean look-up in such cases. Let's see how this works via a few examples.

In the simplest case, you may want to know about the existence of a bean with a certain type (let's say a Discount) because you are not certain if it was deployed given a particular system configuration. Here is how you can do it:
@Inject private Instance discount;
...
if (!discount.isUnsatisfied()) {
Discount currentDiscount = discount.get();
}

In the example above, we are injecting the typed Instance for the discount bean. Note, this does not mean that the discount itself is injected, just that you can look-up discounts as needed via the typed Instance. When you need to query for the discount, you can check if it exists via the isUnsatisfied method. You can also check for ambiguous dependencies if you need to. If the discount was deployed, you can then actually get the resolved bean and use it. If you need to, you can apply qualifiers to an Instance. For example, you can look for a holiday discount as below:
@Inject @Holiday private Instance discount;
Now let's assume that there might be multiple matches for a particular bean type/qualifier - there is likely more than one discount, for example. You can handle this case by placing the @Any annotation on an Instance as below and iterating over all the matches:
@Inject @Any private Instance anyDiscount;
...
for (Discount discount: anyDiscount) {
// Use the discount...
}

Note that Instance is an Iterable as a convenience, which is why the abbreviated foreach loop syntax above works. If needed, you can narrow down the matches by qualifier and/or sub-type at runtime. This is how you could filter by qualifier:
@Inject @Any private Instance anyDiscount;
...
Annotation qualifier = holiday ? new Holiday() : new Standard();
Discount discount = anyDiscount.select(qualifier).get();


The select method allows you to narrow down the potential discount matches by taking one or more qualifiers as arguments. If it's a holiday, you would be interested in holiday discounts instead of standard discounts in the example code. You can also pass a bean sub-type to the select method as below:
Instance sellerDiscount =
anyDiscount.select(SellerDiscount.class, new Standard());

There is much more to the Instance construct that you should definitely check out by taking a look at the CDI specification itself (or the Weld reference guide). You can also use the CDI SPI intended for creating portable extensions to look up beans in a more generic fashion. We will cover portable extensions in a future article in the series.

Tuesday, January 19, 2010

JAX-WS Implementations

There are multiple APIs for the Java platform, e.g. for database access or web applications. The developer has to code against a standard not against a product. The particular tools and servers stay replaceable. For example a web application can be operated with both the Application Server IBM Web Sphere and the Web Container Apache Tomcat. Due to the standardization by the Java Enterprise Edition the exchange of a server can be done with little effort.

Unfortunately, Web Services are a different story. Indeed there is the JAX-WS specification, but there are still too many unanswered questions as well as alternative approaches of applying Web Services. Which SOAP implementation is suitable depends on the requirements and the environment. The sections below are describing the tools and standards that are available for developers of Web Services.

Apache Axis2
Axis 2 is the follow-up of the popular Axis1 framework. Axis2 is based on a completely new architecture and has been re-developed from scratch.

The deployment of services for Axis 1 has often been criticized. Therefore Axis 2 has a completely new deployment model. An Axis 2 runtime is a Web application and can be installed on every JEE compliant Application Server. The Axis 2 web application itself is a container for Web Services now. Web Services are packed into an own file format with the file extension aar. Due to these archives, Web Services can be installed and configured by a simple user interface at run time. In Axis 2 the services can be configured by the traditional deployment descriptors, e.g. the file services.xml.

Modules providing additional functionality, for example WS-* standard support, can also be installed during runtime. A Web Service is regarded as an independent package which can be installed into the Axis 2 runtime environment.

Writing an Axis 2 project requires a lot of knowledge about the build tool Ant. Knowledge about the build tool is essential to write an Axis 2 project. For example the WSDL2JAVA task is generating a temporary project including a build-file. Then the projects build-file has to call the generated build-file. If a Web Service uses a library, e.g. a JDBC driver, then the library has to be copied into the generated project using Ant on each build. So development with Axis 2 will be very difficult if you are not familiar with Ant.

Apache CXF
CXF is also a project of the Apache software foundation. CXF came up from a fusion of the XFire and Ionas Celtix projects.

CXF was developed with the intention to integrate it into other systems. This is reflected in CXF API and the use of the Spring framework. Therefore it is very simple to integrate CXF into existing systems.

CXF respectively its predecessor XFire was integrated into numerous open and closed source projects like ServiceMix or Mule.

A proprietary API as well as the standardized JAX-WS interface are available for the development and use of Web Services.

JAX-WS
The Java API for XML based Web Services is the successor of the JAX-RPC specification. JAX-WS respectively its predecessor is message based and supports asynchronous communication. The Configuration is managed by annotations therefore Java 5 or higher is required. JAX-WS isn't downwardly compatible to its predecessor JAX-RPC. With JAX-WS it is pretty easy to write and consume Web Services. The default values of numerous parameters are comfortable for the programmer, so that simple Pojos declared with a @WebService annotation can be used as a Service. Listing 1 shows a simple implementation of a Web Service using the @WebService annotation.

import javax.jws.WebService;
import javax.jws.WebMethod;

@WebService
public class HelloWorldService {

public String helloWorld() {
return "Hello World!";
}
}

Listing 1: HelloWorld Web Service using JAX-WS

A suitable WSDL document can also be generated from the class. Other annotations can concertedly exert influence of the WSDL document. For example other namespaces or element names can be used. If JAXB is already known, its annotations can be used to define the serialization in every detail. With the contract first approach a Service Interface, JAXB annotated classes for serialization and a skeleton for the implementation can be generated. According to the WSDL document the generated classes can have numerous annotations. Annotations are also the main point of criticism of JAX-WS. Despite this criticism the JAX-WS specification came out well. It is well attuned and combinable with other Java and Java EE specifications. For example, Listing 2 shows a stateless EJB 3.0 Bean which acts as a Web Service at the same time.

@WebService
@Stateless
public class MyService{
public String hello(String name) {
return "Hallo"+name;
}
}

Listing 2: Stateless SessionBean acting as Web Service

JAX-WS Reference Implementation
The JAX-WS Reference Implementation represents the core piece of the Web Services protocol stack Metro. The Metro Stack provides support for the following Web Services standards:

WS-Addressing
WS-Policy
Web Services Security aka WS-Security
WS-Transaction
WS-Reliable Messaging
WS-Trust
WS-SecureConversation

Metro is documented in detail. Apart from the JAX-WS, JAXB and JWS specifications there are numerous tutorials und samples. The Netbeans IDE as well as the tutorials of the enterprise pack makes it particularly easy to get started. Of course, Eclipse can also be used for the development with Metro.

Web applications containing Web Services which have been realized with JAX-WS are executable in the Glassfish Application Server. To make services also executable in other application servers, two libraries (JAX-WS and JAXB) have to be installed. Application servers such as JBoss, WebSphere or Tomcat can be upgraded with JAX-WS within about 10 minutes.

Performance
Due to the modern streaming XML parser, the performance of all three SOAP engines is very well. The ping time for a locale roundtrip is about 2-4 milliseconds (message size about 3KB, Dual Core Notebook). Therefore the time delay by the SOAP communication is negligible in many projects.

WS-* Standards
The support of the WS-Standard family can also be decisive for the selection of a SOAP engine. For example, messages sent to services can be secured with signatures as described in the Web Service Security standard (in short WSS). Table 1 shows the support for WS*-Standards of the toolkits.

Conclusion
None of the Web Services frameworks is in general superior to the others. Axis 2 is structured modularly, has many features and can be used as an application server for Web Services. A special feature of Axis 2 is the support of removable binding frameworks, for example XMLBeans. Axis 2 together with the XMLBeans framework included is well suited for Web Services which are using very complex schema definitions. The disadvantages of Axis 2 are its complexity as well as the insufficient JAX-WS support. Therefore anyone who wants to work with JAX-WS should choose Apache CXF or the reference implementation.

Those who prefer a seamless integration with the Spring framework are well advised with the JAX-WS implementation. Furthermore CXF is slim and easy to use. CXF is the tool of choice if a SOAP engine has to be embedded into an existing software.

Who just wants to code against the standard is well advised with the JAX-WS implementation. The enterprise pack of the Netbeans development environment supports JAX-WS RI very well. Only a few clicks are needed to build a server or to call a Web Service.

I hope this article could help you with the decision for a WS toolkit.

StandardsAxis2CXFJAX-WS/Metro
WS-AddressingXXX
WS-CoordinationX(2)X
WS-MetadataExchangeX
WS-PolicyXXX
WS-ReliableMessagingX(3)XX
Web Services SecurityX(1)X(4)X
WS-SecureConversationX(1)X
WS-SecurityPolicyX
WS-TransactionX(2)X
WS-TrustXX
WS-Federation

Table 1: Support for WS-* Standards (stand: Juli 2008)

(1) Supported by the additional module Apache Rampart
(2) Supported by the additional module Apache Kandula2
(3) Supported by the additional module Apache Sandesha2
(4) By Apache WSS4J Interceptor

JAX-RCP vs JAX-WS

JAX-RPC
A specification/API for Java developers to develop SOAP based interoperable web services. This API is now obsolete, and may be dropped from the next JEE version.

JAX-WS
The successor to JAX-RPC. It requires Java 5.0, and is not backwards-compatible to JAX-RPC. This article describes the high-level differences to JAX-RPC.

SAAJ
Another specification/API for using SOAP envelopes with or without attachments. It operates on a lower level than JAX-RPC or JAX-WS, both of which will use SOAP envelopes based on SAAJ if needed.

JAX-RPC 2.0 (Java API for XML Based RPC) has been renamed to JAX-WS 2.0 (Java API for XML Web Services).

This was done for a number of reasons, but the main reasons are:
The JAX-RPC name is misleading, developers assume that all JAX-RPC is about is just RPC, not Web Services.

By renaming JAX-RPC to JAX-WS we can eliminate this confusion. JAX-RPC 2.0 uses JAXB for all databinding.

As the bindings are different in JAX-RPC 1.1, it introduced a number of source compatibility issues. The migration from JAX-RPC 1.1 to JAX-RPC 2.0 is not cookie cutter as generated Java code and schemas will be different than those generated by JAX-RPC 1.1.

Although the renaming does not ease this migration, it does let the developer know that these are two separate technologies, hence the more difficult migration is more palatable.

Maintaining binary compatibility with the JAX-RPC 1.1 APIs, was hindering our goal of ease-of-development. Because we had this binary compatibility requirement, many legacy APIs were exposed such as the various methods on javax.xml.rpc.Service and the javax.xml.rpc.Call. Having these legacy APIs around would confuse developers. By renaming JAX-RPC 2.0 to JAX-WS 2.0 we no longer have this binary compatibility requirement and we can rid the APIs of these legacy methods and interfaces and we can focus on a new set of APIs that are easier to understand and use.

WebService Implementations
Apache Axis
An open source implementation of the Java WS APIs for sending and receiving SOAP messages. Axis 1 supports JAX-RPC and SAAJ, while Axis 2 supports SAAJ and JAX-WS.

Apache SOAP
The first SOAP implementation. It is now obsolete. It's better to use Apache Axis to avail oneself of the latest features.

Sun JWSDP
Sun Java Webservices Developer Pack, is an implementation of JAX-RPC, SAAJ and various other XML Java technologies. It is now deprecated in favor of GlassFish.

Metro
The web services stack used in GlassFish?. It supports SAAJ, JAX-WS, WS-Security and other standards.

JAX-RS
It is a Java API for RESTful web services.
Jersey is the reference implementation of the JAX-RS API, as defined in the JSR-311 standard for RESTful web services.

For more info, see http://faq.javaranch.com/java/WebServicesFaq.