JMS with Weblogic Server and EJB MDB

Here is a complete and short example of asynchronous development using JMS and a Message-Driven Bean (MDB).
First the procedure to configure inside Weblogic Server a JMS server in order to create a queue, then the code for the producer/sender of a message to the queue and then the code for a consumer (MDB).

1) Weblogic configuration
a) Create the JMS server

JMS_Weblogic1

JMS_Weblogic2

JMS_Weblogic3

JMS_Weblogic4

b) Create a JMS module
JMS_Weblogic5

JMS_Weblogic6

JMS_Weblogic7

JMS_Weblogic8

JMS_Weblogic9

JMS_Weblogic10

JMS_Weblogic11

JMS_Weblogic12

c) Create a destination (queue or topic)

JMS_Weblogic13

JMS_Weblogic14

JMS_Weblogic15

JMS_Weblogic16

d) Create a connection factory

JMS_Weblogic17

JMS_Weblogic18

JMS_Weblogic19

2) Create a producer

For the producer, I got strongly inspired by the code found in this blog. This is a clean example of a producer/sender so no need to reinvent the wheel here.

import java.util.Hashtable;

import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class JMSProducer {

	private static InitialContext initialContext = null;
	private static QueueConnectionFactory queueConnectionFactory = null;
	private static QueueConnection queueConnection = null;
	private static QueueSession queueSession = null;
	private static Queue queue = null;
	private static QueueSender queueSender = null;
	private static TextMessage textMessage = null;
	private static final String CONNECTIONFACTORY_NAME = "ConnectionFactory-Test";
	private static final String QUEUE_NAME = "jms/QueueTest";

	public JMSProducer() {
		super();
	}

	public static void sendMessageToDestination(String messageText) {
		// create InitialContext
		Hashtable properties = new Hashtable();
		properties.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
		properties.put(Context.PROVIDER_URL, "t3://localhost:7001");
		properties.put(Context.SECURITY_PRINCIPAL, "weblogic");
		properties.put(Context.SECURITY_CREDENTIALS, "weblogic1");
		try {
			initialContext = new InitialContext(properties);
		} catch (NamingException ne) {
			ne.printStackTrace(System.err);
		}
		System.out.println("InitialContext : " + initialContext.toString());
		// create QueueConnectionFactory
		try {
			queueConnectionFactory = (QueueConnectionFactory) initialContext.lookup(CONNECTIONFACTORY_NAME);
		} catch (NamingException ne) {
			ne.printStackTrace(System.err);
		}

		System.out.println("QueueConnectionFactory : " + queueConnectionFactory.toString());
		// create QueueConnection
		try {
			queueConnection = queueConnectionFactory.createQueueConnection();
		} catch (JMSException jmse) {
			jmse.printStackTrace(System.err);
		}

		System.out.println("QueueConnection : " + queueConnection.toString());
		// create QueueSession
		try {
			queueSession = queueConnection.createQueueSession(false, 0);
		} catch (JMSException jmse) {
			jmse.printStackTrace(System.err);
		}

		System.out.println("QueueSession : " + queueSession.toString());
		// lookup Queue
		try {
			queue = (Queue) initialContext.lookup(QUEUE_NAME);
		} catch (NamingException ne) {
			ne.printStackTrace(System.err);
		}

		System.out.println("Queue : " + queue.toString());
		// create QueueSender
		try {
			queueSender = queueSession.createSender(queue);
		} catch (JMSException jmse) {
			jmse.printStackTrace(System.err);
		}

		System.out.println("QueueSender : " + queueSender.toString());
		// create TextMessage
		try {
			textMessage = queueSession.createTextMessage();
		} catch (JMSException jmse) {
			jmse.printStackTrace(System.err);
		}

		System.out.println("TextMessage : " + textMessage.toString());
		try {
			textMessage.setText(messageText);
		} catch (JMSException jmse) {
			jmse.printStackTrace(System.err);
		}

		System.out.println("TextMessage : " + textMessage.toString());
		// send message
		try {
			queueSender.send(textMessage);
		} catch (JMSException jmse) {
			jmse.printStackTrace(System.err);
		}

		System.out.println("Message sent.");
		// clean up
		try {
			textMessage = null;
			queueSender.close();
			queueSender = null;
			queue = null;
			queueSession.close();
			queueSession = null;
			queueConnection.close();
			queueConnection = null;
			queueConnectionFactory = null;
			initialContext = null;
		} catch (JMSException jmse) {
			jmse.printStackTrace(System.err);
		}

		System.out.println("Cleaned up done.");
	}

	public static void main(String args[]) {
		sendMessageToDestination("test");
	}
}

3) Create a consumer

This MDB consumer just prints out something in the log when it consumes the message in the queue.
The lifecycle methods are empty but they could be used to clean up resources for instance.

import javax.ejb.ActivationConfigProperty;
import javax.ejb.EJBException;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@MessageDriven(mappedName = "jms/QueueTest", activationConfig = {
		@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
		@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") })
public class TestJMSSABean implements MessageDrivenBean, MessageListener {

	/** The Constant LOGGER. */
	protected static final Logger LOGGER = LoggerFactory.getLogger(TestJMSSABean.class);

	public TestJMSSABean() {
	}

	@Override
	public void onMessage(Message message) {
		try {
			if (message instanceof TextMessage) {
				System.out.println(((TextMessage) message).getText());
				LOGGER.trace("***************** : " + ((TextMessage) message).getText());
			} else {
				System.out.println(message.getJMSMessageID());
				LOGGER.trace("***************** : " + message.getJMSMessageID());
			}
		} catch (JMSException ex) {
			LOGGER.trace("***************** ERROR : " + ex.getMessage());
		}
	}

	@Override
	public void ejbRemove() throws EJBException {
		// TODO Auto-generated method stub
	}

	@Override
	public void setMessageDrivenContext(MessageDrivenContext arg0) throws EJBException {
		// TODO Auto-generated method stub
	}
}

Unit testing EJBs with PowerMockito

I had to find a way to test a method from a stateful session bean (EJB PersonSABean implements PersonSF) defined in a service layer that calls another method from another stateful session bean (EJB HouseSFBean implements HouseSF) defined in a business layer.

To call that method from EJB HouseSFBean, the EJB PersonSABean needs to perform a lookup to get a reference to the EJB HouseSF. In that case, a static method is often created inside a static or final class. For instance :

public final class EjbUtil {
public static <T> T lookup(final Class<T> clazz) throws SomeException {
 InitialContext context = null;

try {
 context = new InitialContext(new PropertiesLoader().loadProperties("myProperties.txt"));
}
 return clazz.cast(context.lookup(name));
} catch (NamingException e) {
 throw new SomeException(e.getMessage());
} finally {
...
}

...

}
@TransactionManagement(TransactionManagementType.CONTAINER)
@Stateless(name = "PersonSA")
@Remote(value = { PersonSA.class })
@Interceptors(HandlerExceptionInterceptorSA.class)
public class PersonSABean extends BasicSABean implements PersonSA {
 ...
 private HouseSF houseSF;

 public HouseSF getHouseSF() {
    houseSF = EjbUtil.lookup(PersonSF.class, "ejb.company.project.application.HouseSF");
    return houseSF;
 }
}

But unit tests, unlike integration tests, are meant to test a specific method (or class). They are not meant to test the methods that it calls. So in my case, i do not need  to make – and should not make – a JNDI lookup to get a reference to the EJB HouseSF . So I have to mockup the EjbUtil.lookup(…)  static method.

Fortunately, PowerMockito can mock a static method so the solution is to use both Mockito and PowerMockito :

@RunWith(PowerMockRunner.class)
@PrepareForTest(EjbUtil.class)

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyListOf;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.stub;

import java.util.ArrayList;
import java.util.List;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@Category(UnitTest.class)
@RunWith(PowerMockRunner.class)
@PrepareForTest(EjbUtil.class)
public class PersonSABeanTest {

@Mock
private HouseSF houseSF;

private PersonSABean personSABean;

@Before
public void setUp() throws Exception {
  MockitoAnnotations.initMocks(this);
  personSABean = new PersonSABean();
  personSABean.setHouseSF(houseSF);
  PowerMockito.mockStatic(EjbUtil.class);
}

@Test
public void testSomeMethod() throws SomeBusinessException {
  ...
  SomeDTO someDTO = new SomeDTO();
  stub(houseSF.someMethod(anyListOf(A.class), anyListOf(BDTO.class), any(CDTO.class), anyInt())).toReturn(someDTO);
  Mockito.when(EjbUtil.lookup(anyString(), Mockito.eq(HouseSF.class), anyString())).thenReturn(houseSF);
  ...
}

Link :
https://code.google.com/p/powermock/wiki/MockitoUsage13


			
				
			
			

Eclipse Dali vs Hibernate Tools

The process of mapping tables to entities is greatly simplified with tools like Eclipse Dali and Hibernate Tools, both available as Eclipse plugins. It avoids mapping them by hand, which in my opinion is prone to mapping errors and takes more time. And I really do not see why one should map them by hand when great tools like Eclipse Dali and Hibernate Tools are available.
In my book, I describe the use of the Eclipse Dali plugin to automatically generate the entities.
Lately I have also used Hibernate Tools and I have already noticed a few differences between these two tools.
I am going to list some of these differences.
Continue reading

Code for the book is now on GitHub

I finally added the code for the book “Les EJB 3 (avec Struts 2, JSF 2, JasperReports 3, Flex 3)” to GitHub.

To grab it, you have 2 options :
1) use GIT and type :
git clone git://github.com/longbeach/VenteEnLigne.git
2) use SVN and type :
svn co http://svn.github.com/longbeach/VenteEnLigne

As a matter of fact, and surprising as it might sound, you can use SVN to grab code from GitHub 🙂

Enterprise JavaBeans 3.1, sixth edition, available now

I just noticed that the sixth edition of the book Enterprise JavaBeans, updated to the specification 3.1, from O’Reilly, by Andrew Lee Rubinger (JBoss) and Bill Burke (JBoss), is now available.
I am looking forward to reading it.
The book does not focus on any specific application server. As mentioned in the introduction :

“Because the focus of this book is on developing vendor independent EJB components and solutions, we have stayed away from proprietary extensions and vendor-dependent idioms wherever possible. You can use any EJBcompliant server with this book, but you should be familiar with your server’s specific installation, deployment, and runtime-management procedures to work with the examples.”

Continue reading

My book on EJB 3 is now on sale

I received an email from the editor informing me that the book is now printed and will be available in bookstores next week (from July 5th, 2010).

It is already available for sale on Amazon and ENI.

An online version is also available.

Here is the cover of the book :

SO3EJB_max

DAO design pattern in a session bean ?

I have recently been challenged by a colleague with a .Net background about the way I sometimes use session beans in web applications. Indeed, I like to implement DAOs as session beans.
Some people argue that it’s best not to directly implement CRUD methods in session beans.
The main reason being that they prefer to add another level of separation. For instance :

Session bean client
!
Session bean
!
business object helper class
!
DAO
!
ORM (Hibernate)
!
Database

A good example of this approach is the old implementation (EJB 2.0) of the The Java Pet Store by Sun. (API : http://java.sun.com/blueprints/code/jps131/src/).
My opinion is that this level of separation is not always necessary. And I believe using session beans as DAOs makes even more sense now that in EJB 3.x we have the Java Persistence API (entitymanager)  which already provides generic
database access methods (persist(), merge(), etc) :

Session bean client
!
Session bean DAO (JPA)
!
Entity bean
(JPA)
!
Database

Adam Bien explains it well in this post.