Service POJOs

Service POJOs are the new generation of JBoss services. While you can keep programming MBeans in the standard way (building an MBean interface, an implementation class, and XML descriptors), you can simplify the process of developing MBeans with service POJOs. Actually, service POJOs are plain Java classes with some annotations that denote the special nature of the component.

The way you define them is very similar to defining Stateless or Stateful Session Beans. One very important difference is that there will only be one instance of the service bean, that is, it is not pooled—the bean instance is a singleton. The singleton bean contains shared state, so data set by one client is accessible by other clients.

Let's see a concrete example. We will create a CurrencyConverter service that converts a sum of money from Euros into other currencies. A service like this is an ideal example of a singleton service that can be shared across other components of your applications.

Add an interface named com.packtpub.jmx.example4.CurrencyConverter to your project.

This interface will contain the life cycle methods of your servicePOJO, the getter/setter methods, and the management methods:

package com.packtpub.jmx.example4;
public interface CurrencyConverter {
public String getCurrency();
public void setCurrency(String currency);
// The management method
public double convert (double amount);
// Life cycle method
public void create () throws Exception;
public void destroy () throws Exception;
}

The implementation class follows here:

package com.packtpub.jmx.example4;
import java.util.HashMap;
import javax.ejb.Local;
import org.jboss.ejb3.annotation.LocalBinding;
import org.jboss.ejb3.annotation.Service;
import org.jboss.ejb3.annotation.Management;
@Service(objectName = "servicePOJO:service=CurrencyConverter")
@Management(CurrencyConverter.class)
public class CurrencyConverterService implements CurrencyConverter {
private String currency;
private HashMap<String, Double> mapCurrency = new HashMap();
public double convert(double amount) {
double currVal = new Double(mapCurrency.get(currency));
return (currVal * amount);
}
// Lifecycle methods
public void create() throws Exception {
System.out.println("CurrencyConverterMBean - Creating");
mapCurrency.put("USD", new Double(1.40));
mapCurrency.put("YEN", new Double(135));
mapCurrency.put("GBG", new Double(0.85));
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public void destroy() {
System.out.println("CurrencyConverterMBean - Destroying");
}
}

Like standard MBeans, POJO services need to define an ObjectName—the @Service annotation is used for this purpose. It defines the object name for this MBean using the same pattern we have already learned: domain:property=value.

The other mandatory annotation is @Management. When JBoss finds this annotation, it will look for the corresponding interface in order to set up an MBean with the defined attributes and operations.

For the sake of simplicity, the list of currencies is stored in a HashMap, which is loaded in the create() life cycle method. Implementing life cycle methods is not mandatory, you can just choose among the following ones that are needed by your service:

  • create(): Called by the server when the service is created, as well as when all dependent services are created. Here the service is registered among services yet not fully functional.
  • start(): Called by the server after create(), when all the initialization process is completed. At this point, the service is ready to serve requests (and so are all the services it depends on).
  • stop(): Called by the server when the service is stopped. At this point the service (and all the services that depend on it) is no longer fully operational.
  • destroy(): Called by the server when the service is removed from the MBean server.

Your ServicePOJO is now ready to be deployed. As you can see in the following screenshot, the structure of a service POJO is not different from a plain Java library:

Service POJOs

That being said, deploy your ServicePOJO as standalone JAR archive or as part of the MBean project and verify from your JMX console that your service has been correctly registered under the ServicePOJO domain:

Service POJOs

Creating a web test client

A sample scenario for your service POJO is an Enterprise application that requires a currency conversion for international orders. Again we will use our JMX Web Client project that we have set up for the SimpleService MBean.

Now add a simple JavaServer Pages (JSP) technology to your project, which will be in charge of contacting the CurrencyPOJO service and invoke the convert() method:

<%@ page import="javax.management.*,com.packtpub.jmx.example4.*, org.jboss.mx.util.*"%>
<%
CurrencyConverter cal = null;
try {
int amount = 250;
MBeanServer server = MBeanServerLocator.locate();
cal = (CurrencyConverter) MBeanProxyExt.create( CurrencyConverter.class, "servicePOJO:service=CurrencyConverter", server);
cal.setCurrency("USD");
out.println(amount + " EURO equal to " + cal.convert(amount) + " " + cal.getCurrency());
}
catch (Exception e) {
e.printStackTrace();
}
%>

The code is self-explanatory—we are creating a proxy for CurrencyConverter using the MBeanProxyExt factory. Then the convert method is recalled to exchange some USD amount into Euros.

Before testing, pack your web application and the MBean project in an Enterprise ARchive (EAR). The following screenshot is a view of your application from the Project Explorer:

Creating a web test client

Packaging your application requires a little patch to your META-INF/application.xml. As a matter of fact, Eclipse by itself doesn't mention Java libraries in this configuration file, so you have do add the MBeanExample.jar archive manually:

<application>
<module>
<web>
<web-uri>JMXWebClient.war</web-uri>
<context-root>JMXWebClient</context-root>
</web>
</module>
<module>
<java>MBeanExample.jar</java>
</module>
</application>

Exposing your service as an EJB

Sometimes you might find it useful to expose your service POJO with a local or remote interface. Using this approach you don't deal with the MBeanProxyExt interface from your client anymore, rather you can inject your service reference into your Enterprise components, just the same way you would do with an ordinary EJB.

Morphing your service into an EJB requires just two small additions to your service. Depending on whether you need a local or remote interface (or both of them), you need to add the @Local or @Remote annotation:

import javax.ejb.Local;
import org.jboss.ejb3.annotation.LocalBinding;
import org.jboss.ejb3.annotation.Service;
import org.jboss.ejb3.annotation.Management;
@Service(objectName = "sampleJMX:service=CurrencyConverter")
@Management(CurrencyConverter.class)
@Local(CurrencyConverter.class) [1]
@LocalBinding(jndiBinding = "service/CurrencyConverter") [2]
public class CurrencyConverterService implements CurrencyConverter {
}

Here we are exposing the service through the CurrencyConverter interface that has been marked as local interface [1] and bound to the JNDI naming context service/CurrencyConverter [2] (the same annotations you would normally use in an EJB 3 session bean).

You can safely inject your POJO service into either a web component or another EJB. As we have already set up a web application, the simplest test would be to add a servlet that interacts without POJO service:

public class ServletConverter extends HttpServlet {
@EJB(mappedName="service/CurrencyConverter")
CurrencyConverter currLocal;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
int amount = 300;
currLocal.setCurrency("GBG");
out.println(amount +" EURO equal to " +currLocal.convert(250)+ " " +currLocal.getCurrency());
}
}

This should produce the same output as your JSP. The concrete difference is that our web application is now dealing with a singleton EJB.

Service POJO dependency

MBean dependency can be applied to a service POJO in much the same way as we have shown with standard MBeans. The annotation used to specify a dependency is @Depends. Here we are stating that our CurrencyConverterService will not start until our DataSourceBinding service is available.

@Depends ("jboss.jca:name=MySqlDS,service=DataSourceBinding")
public class CurrencyConverterService implements CurrencyConverter
{
}

This annotation can also be used for injecting a service in our POJO:

@Depends ("servicePOJO:service=AnotherService")
public AnotherService service;

This way, our POJO service will wait for AnotherService to be available. When this service is started, it is injected into the instance field service and thus it is accessible to our service.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.100.20