Thursday, August 24, 2006

Using EJB 3.0 Message Driven Bean with JCA-Resource Adapters

MDB was the only bean type that did not suffer obesity problems with EJB 2.x. It was simple to develop and use and it was liked by most developers.

For many developers the verbose XML descriptor was still a sour-point. EJB 3.0 further simplified message driven bean by removing the requirement to use descriptors and you can use annotations to specify the activation config properties.

An Example MDB with EJB 3.0 Annotations

A simple MDB will look like as follows:

@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "ConnectionFactoryJndiName", propertyValue = "jms/TopicConnectionfactory"),
@ActivationConfigProperty(propertyName = "DestinationName", propertyValue = "jms/demoTopic"),
@ActivationConfigProperty(propertyName = "DestinationType", propertyValue = "javax.jms.Topic"),
@ActivationConfigProperty(propertyName = "messageSelector", propertyValue = "RECIPIENT = 'MDB'")
})

public class MessageLogger implements MessageListener{..}

This problem with MDB is that it works will the default JMS provider of the container i.e . in-memory JMS provider of OracleAS.

Using MDB with a JCA-compliant Resource Adapter

There are many instances probably you want to use a messaging provider (JMS or non-JMS) plugged-in using a JCA-compliant connector or resource adapter. Let us assume that OracleAS JMS wit the global connector (named OracleASjms) packaged with Oracle AS. Unfortunately EJB or JCA does not standardize configurations for using a resource adapter and you have to depend upon a proprietary feature such as vendor specific annotation or activation config property to designate the resource adapter to be used with your MDB. Oracle provides a vendor specific annotation (@oracle.j2ee.ejb.MessageDrivenDeployment) to specify Oracle specific configuration properties and you need to use resourceAdapter element to specify the resource adapter that you intend to use. For example you can modify the above MDB as follows to use the OracleASjms global connector to use the In-memory JMS as follows:

@oracle.j2ee.ejb.MessageDrivenDeployment(resourceAdapter="OracleASjms")@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "ConnectionFactoryJndiName", propertyValue = "OracleASjms/MyTCF"),
@ActivationConfigProperty(propertyName = "DestinationName", propertyValue = "jms/demoTopic"),
@ActivationConfigProperty(propertyName = "DestinationType", propertyValue = "javax.jms.Topic"),
@ActivationConfigProperty(propertyName = "messageSelector", propertyValue = "RECIPIENT = 'MDB'")
})

public class MessageLogger implements MessageListener {.}

Note that we have modified the ConnectionFactoryJndiName to use a pre-configured connection factory OracleASjms/MyTCF.

Using a non-JMS Connector

Let us assume that you want to use your own non-JMS resource adapter let us say thirdra then your EJB 3.0 MDB will look as follows:

import oracle.j2ee.ejb.MessageDrivenDeployment;
import thirdra.common.ThirdListener;

@MessageDriven(name="thirdmdb",messageListenerInterface=ThirdListener.class)@MessageDrivenDeployment(resourceAdapter="thirdra")
public class MessageLogger

Isn’t is simpler than EJB 2.x where you had to handle at least two XML descriptors? If you want to use mix-n-match with descriptor (ejb-jar.xml) make sure that version is set to "3.0" in your ejb-jar element otherwise annotations will not be parsed and container will treat it as an EJB 2.1 descriptor.

However I strongly feel that specifying a resource adapter should be standardized by the future release of specification.

Thursday, August 17, 2006

Top 5 features you would care about in OC4J 10.1.3.1!

OC4J 10.1.3.1 Developer Preview was released couple of days back. OC4J 10.1.3.0 was released in January that had a truckload of features. A question that might comes to your mind: Is OC4J 10.1.3.1 a patch release? From Java developer’s perspective OC4J 10.1.3.1 may not be feature-rich like OC4J 10.1.3.0. However it has a lot of features that you might care about.

1. It now has complete implementation of EJB 3.0/JPA final specifications. It means you will see several changes in the EJB container, that includes:
  • EJB 3.0 Persistence now fully aligns with the spec.
  • Lifecycle listeners and Interceptors are aligned with the spec.
  • XML descriptors support is aligned with the spec.

See the updated demos at EJB 3.0 Resource Center.

2. We have added Oracle specific annotations for easier configurations. If you hate descriptors you have an option to make EJB configurations without having to use orion-ejb-jar.xml. Additionally we have added many proprietary enhancements to make usage of EJB 3.0 simpler. We have made persistence.xml optional in an ejb-jar module for packaging entities and use @Resource to inject the EntityManager for the default persistence unit. I will blog about these later.

3. Dependency injection is supported in the application client container and web container. You can use JSR 250 annotations in the web container. and also you can package entities in the web container. Also we have added the library module support in the application level. You can add a lib directory in the EAR level and any jars put in the lib directory will available to all modules in the EAR.

4. We implemented dynamic byte code generation for EJB wrappers and that greatly improves deployment of EJB applications. Most EJB applications should see between 30-70% improvement in deployment from OC4J 10.1.3 in identical configurations.

5. We have added a lot of new ANT tasks to make your life easier e.g. creation of data sources, JMS objects, shared libraries, etc.

Beside that we have a lot of bug fixes. So please try out and give us your feedback.

Here is link again : http://www.oracle.com/technology/tech/java/oc4j/10131/index.html

Tuesday, August 15, 2006

Oracle SOA Suite - Complete EJB3 and JPA Support

Yesterday Oracle released Oracle Application Server 10g (10.1.3.1) Developer Preview. The goal for this release to simplify development and deployment of service-oriented applications and hence it is termed as SOA Release. The SOA suite provides complete set of service infrastructure components such as Enterprise Service Bus, BPEL, BAM and Web Services Manager for creating, deploying and managing services, all available in a single install.


If you are an enterprise java developer and do not care about SOA, OracleAS 10.1.3.1 has something for you too. O It has complete support for EJB 3 and Java Persistence API and has annotations support in the Servlet container. OC4J 10.1.3.1 includes TopLink Essentials as the EJB3 JPA Provider.



You can download JDeveloper 10.1.3.1 and OC4J 10.1.3.1 standalone and to build and deploy EJB3/JPA applications.


See EJB3 Resources for updated howtos, samples, articles, etc.

Monday, August 14, 2006

Developing a Spring-enabled Session bean

In one of my blog entries last month I showed how you could access an EJB 3.0 Session bean from Spring 2.0 beans. One of the readers wanted to know whether it is possible to use Spring with EJB 3.0. Interestingly Spring documentation does not say anything about EJB 3.0 beans support with Spring 2.0. I managed to get this to working Spring 2.0 RC2 and in this article; I will show how you can develop a Spring-enabled EJB 3.0 Session bean.

Spring-enabled EJB 3.0 Session bean.

Spring provides abstract classes such as org.springframework.ejb.support.AbstractStatelessSessionBean and org.springframework.ejb.support.AbstractStatefulSessionBean that you can use to build a Spring-enabled EJB 3.0 session bean. You have to extend the abstract session bean class and implement the onEjbcreate method where you can retrieve the required bean instance from the bean factory as in the following example:

@Stateless
public class EmployeeFacadeBean extends
AbstractStatelessSessionBean implements EmployeeFacade
{

EmployeeServiceBean empService;

protected void onEjbCreate()
{

empService = (EmployeeServiceBean)
getBeanFactory().getBean("empService");

}

public Employee addEmployee(String empName, double sal) {

return empService.addEmployee(empName,sal);
}

..
}

Note that our stateless session bean EmployeeFacadeBean extends AbstractStatelessSessionBean. Note that we have implemented the onEjbCreate method that retrieves instance of EmployeeServiceBean from the bean factory.

The EJB deployment descriptor

The application context is passed to the Session Bean by using an environment variable named ejb/BeanFactoryPath in the deployment descriptor (ejb-jar.xml) as follows:

<session>
<ejb-name>EmployeeFacadeBean</ejb-name>
<env-entry>
<env-entry-name>ejb/BeanFactoryPath</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>/howto-service.xml</env-entry-value>
</env-entry>
</session>

Note that the howto-service.xml contains the bean factory configuration that we see next. The howto-service.xml is packaged in the ejb-jar module.

Wiring all together with Spring configuration


The howto-service.xml contains the Spring configuration.
The
EmployeeServiceBean uses EmployeeDAO that is injected using setter injection:

<beans>

<bean id="empService" class="oracle.ejb30.EmployeeServiceBean">
<property name="employeeDAO">
<ref bean="employeeDAO">
</ref>
</property>
..
</bean>




Remember that the Spring enabled EJB 3.0 Session bean (EmployeeFacadeBean) invokes the EmployeeService bean from the bean factory

empService = (EmployeeServiceBean) getBeanFactory().getBean("empService");


Client Code:

Let us assume that a servlet accesses the Spring-enabled EJB as follows:

public class InsertServlet extends HttpServlet
{
@EJB
private EmployeeFacade ef;

..

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String name = "";
Double sal = new Double(0);

name = request.getParameter("empName");
sal = Double.valueOf(request.getParameter("Sal"));
try
{
Employee emp = ef.addEmployee(name,sal);
System.out.println("Successfully persisted an employee");
request.setAttribute("emp",emp);
this.getServletContext().getRequestDispatcher("/jsp/success.jsp").forward(request, response);
}
catch(Exception e)

}



If you look at the above code you will see that the Servlet uses dependency injection using @EJB (Java EE) to get an instance of Spring-enabled EJB and then invoke its method.


Conclusion


After you package your application, you should be able to deploy and run the application that uses a Spring-enabled EJB 3.0 session bean. Note that I tested this with Oracle Application Server 10g and I expect it to work in other application servers that support EJB 3.0. In a follow-up blog, I will discuss how you can use Spring’s JpaTemplate with a container-managed EntityManager within a Java EE container.

Thursday, August 10, 2006

Same house and same job but a new blog!

Changes are part of our life! New car, new computer or new kids are always fun! They bring excitement to life. But sometime we have emotional attachment to old things, old houses, etc. And I had the same with my old blog-site (http://radio.weblogs.com/0135826/) and was resisting for a change. I used Radio UserLand for more than two and half years and although I never liked it user interface, ability to restore old blogs I was still emotionally attached that being my first blog site.

Finally I decided to desert it. Some shortcomings in Radio Userland literally drove me crazy and I was not able to blog almost for a month after my laptop crashed! I had to pay Price for Carelessness.

My old blog site was getting fairly good number of hits averaging around 300 hits a day with some days around 2000-2500 hits. It has a good number of popular and controversial blogs that were linked from many web sites including TheServerSide.com, JavaWorld, java.net, etc and hence leaving the old blog home was not an easy decision. I will try to restore some of my popular old blogs in the new blog site so that these are not lost when my license expires with Radio UserLand and they trash these pages. So stay tuned when I return to normal bogging schedule!