Monday, June 24, 2013

MDB Using Jboss 7

Jboss 7 architecture is completely changed compared to the previous versions. Due to this, there is a change in configuration of queues, connection factories, security etc. Here, we are not going to see how we create MDB, rather we will look at how to configure to work in Jboss7 and how to create a standalone client to send a message to Queue on Jboss7.
Jboss7 has been fully modulated, we treat each and every component of jboss7 as separate module. This has to be done in standalone.xml file. By default, we get different versions of standalone files like standalone, standalone-full etc. I prefer to use standalone.xml and add modules as required.
To enable messaging we need to add the following lines to standalone file
  • In <extensions> tag, add
<extension module="org.jboss.as.messaging"/>
  • Add sub-system in <profile>
<subsystem xmlns="urn:jboss:domain:messaging:1.1">
    <hornetq-server>
        <persistence-enabled>true</persistence-enabled>
        <journal-file-size>102400</journal-file-size>
        <journal-min-files>2</journal-min-files>

        <connectors>
            <netty-connector name="netty" socket-binding="messaging"/>
            <netty-connector name="netty-throughput" socket-binding="messaging-throughput">
                <param key="batch-delay" value="50"/>
            </netty-connector>
            <in-vm-connector name="in-vm" server-id="0"/>
        </connectors>

        <acceptors>
            <netty-acceptor name="netty" socket-binding="messaging"/>
            <netty-acceptor name="netty-throughput" socket-binding="messaging-throughput">
                <param key="batch-delay" value="50"/>
                <param key="direct-deliver" value="false"/>
            </netty-acceptor>
            <in-vm-acceptor name="in-vm" server-id="0"/>
        </acceptors>

        <security-settings>
            <security-setting match="#">
                <permission type="send" roles="guest"/>
                <permission type="consume" roles="guest"/>
                <permission type="createNonDurableQueue" roles="guest"/>
                <permission type="deleteNonDurableQueue" roles="guest"/>
            </security-setting>
        </security-settings>

        <address-settings>
            <address-setting match="#">
                <dead-letter-address>jms.queue.DLQ</dead-letter-address>
                <expiry-address>jms.queue.ExpiryQueue</expiry-address>
                <redelivery-delay>0</redelivery-delay>
                <max-size-bytes>10485760</max-size-bytes>
                <address-full-policy>BLOCK</address-full-policy>
                <message-counter-history-day-limit>10</message-counter-history-day-limit>
            </address-setting>
        </address-settings>

        <jms-connection-factories>
            <connection-factory name="InVmConnectionFactory">
                <connectors>
                    <connector-ref connector-name="in-vm"/>
                </connectors>
                <entries>
                    <entry name="java:/ConnectionFactory"/>
                </entries>
            </connection-factory>
            <connection-factory name="RemoteConnectionFactory">
                <connectors>
                    <connector-ref connector-name="netty"/>
                </connectors>
                <entries>
                    <entry name="RemoteConnectionFactory"/>
                    <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>
                </entries>
            </connection-factory>
            <pooled-connection-factory name="hornetq-ra">
                <transaction mode="xa"/>
                <connectors>
                    <connector-ref connector-name="in-vm"/>
                </connectors>
                <entries>
                    <entry name="java:/JmsXA"/>
                </entries>
            </pooled-connection-factory>
        </jms-connection-factories>

        <jms-destinations>
            <jms-queue name="MyQueue">
                <entry name="queue/MyQueue"/>
                <entry name="java:jboss/exported/jms/queue/MyQueue"/>
            </jms-queue>
        </jms-destinations>
    </hornetq-server>
</subsystem>
  • This creates a queue named MyQueue. Now i can deploy a MDB listening to the queue "MyQueue". Listener class is as follows.
@MessageDriven(activationConfig = {
  @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
  @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/MyQueue") }, mappedName = "MyQueue")
public class QueueListener implements MessageListener {

 private static final Logger logger = Logger.getLogger(QueueListener.class);

 /**
  * @see MessageListener#onMessage(Message)
  */
 public void onMessage(Message message) {
  logger.debug("Inside onMessage");
  try {
   if (message instanceof TextMessage) {

    TextMessage msg = (TextMessage) message;
    logger.info("Message : " + msg.getText());
   }
  } catch (Exception e) {
   logger.error("Exception while processing the message ", e);
  }

 }
}
  • After deploying, start the Jboss7, you will find log saying QueueListener is listening using hornetq-ra resource adapter. Now, it's time to send a message to the Queue. Here is the client which can send the message to the Queue.
public class MDBClient {
 public static void main(String... strings) {
  try {
   final Properties props = new Properties();
   props.put(Context.INITIAL_CONTEXT_FACTORY,     "org.jboss.naming.remote.client.InitialContextFactory");
   props.put(Context.PROVIDER_URL, "remote://localhost:4447");
   props.put(Context.SECURITY_PRINCIPAL, "sample");
   props.put(Context.SECURITY_CREDENTIALS, "sample123");

   InitialContext context = new InitialContext(props);
   QueueConnectionFactory factory = (QueueConnectionFactory) context     .lookup("jms/RemoteConnectionFactory");
   Queue queue = (Queue) context.lookup("jms/queue/MyQueue");
   QueueConnection cnn = factory.createQueueConnection("sample",     "sample123");
   QueueSession session = cnn.createQueueSession(false,     QueueSession.AUTO_ACKNOWLEDGE);
   QueueSender sender = session.createSender(queue);
   TextMessage message = session.createTextMessage();
   message.setText("Text Message");
   sender.send(message);
   context.close();
   cnn.close();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}
  • Run the above code, which sends the message to Jms Queue "MyQueue". Add jboss-client.jar ($JBOSS_HOME/bin/client/jboss-client.jar) to classpath to get it running.
Points to remember
  1. Remote JNDI : A new entry added for RemoteConnectionFactory (java:jboss/exported/jms/RemoteConnectionFactory) to expose it so that it can be called looked up from remote. Same is the case for the queue (java:jboss/exported/jms/queue/MyQueue)
  2. Security: Credentials to be passed to the Context and While creating connection to connect to Queue. The credentials must be of user who belongs to group (guest). User can be setup by using adduser script in $JBOSS_HOME/bin.
  3. Off the Secutiry: We can off the security by adding <security-enabled>false</security-enabled> to the hornetq-server element
  4. Jboss-Client: jboss-client.jar which is added to Standalone client classpath.

Sunday, May 19, 2013

JAXB XML Adapter

JAXB provides XMLAdapter to change the format of default JAXB types. For example, formatting decimal places in Decimal or BigDecimal, Date formatting etc.
How to do it?
First look at the following plain vanilla example of JAXB
package com.test;

import java.math.BigDecimal;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.datatype.XMLGregorianCalendar;

@XmlRootElement
public class Loan {
	private String name;
	private Long amount;
	private XMLGregorianCalendar startDate;
	private BigDecimal interestRate;
	public String getName() {
		return name;
	}
	@XmlElement
	public void setName(String name) {
		this.name = name;
	}
	public BigDecimal getInterestRate() {
		return interestRate;
	}
	@XmlElement
	public void setInterestRate(BigDecimal interestRate) {
		this.interestRate = interestRate;
	}
	public XMLGregorianCalendar getStartDate() {
		return startDate;
	}
	@XmlElement
	public void setStartDate(XMLGregorianCalendar startDate) {
		this.startDate = startDate;
	}
	public Long getAmount() {
		return amount;
	}
	@XmlElement
	public void setAmount(Long amount) {
		this.amount = amount;
	}	
}
If we marshall the Loan object, the output is similar to
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<loan>
    <amount>200000</amount>
    <interestRate>15.6</interestRate>
    <name>Name</name>
    <startDate>2013-05-19T16:02:51.080+05:30</startDate>
</loan>
Now, format the XMLGregorianCalendar to YYYY-MM-DD in XML. For this, we need to add a new XMLAdapter which can convert(marshall) from Calendar format to String format.
package com.test;

import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.datatype.XMLGregorianCalendar;

public class CalendarAdaptor extends XmlAdapter<String, XMLGregorianCalendar> {

	@Override
	public String marshal(XMLGregorianCalendar v) throws Exception {
		return v.getYear()+"-"+v.getMonth()+"-"+v.getDay();
	}

	@Override
	public XMLGregorianCalendar unmarshal(String v) throws Exception {
		return null;
	}
}
and Add the Adapter to the property where we would like to change. So the Loan.java file will be changed at the setStartDate method to following
        @XmlJavaTypeAdapter(CalendarAdaptor.class)
	public void setStartDate(XMLGregorianCalendar startDate) {
		this.startDate = startDate;
	}
When we marshall the same Loan object now, with the above change, the xml string will be
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<loan>
    <amount>200000</amount>
    <interestRate>15.6</interestRate>
    <name>Name</name>
    <startDate>2013-5-19</startDate>
</loan>
But the thing is, we need to change each property for the class definitions to affect this change. Instead of changing the classes, we can provide this adapter change at the package level by defining a class called package-info.java without changing the individual class properties. By doing this, all the XMLGregorianCalendar attributes in the package will follow the format defined by the Adapter. package-info.java
@XmlJavaTypeAdapter(value=CalendarAdaptor.class, type=XMLGregorianCalendar.class)
package com.test;

import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

Sunday, March 17, 2013

Timer Service Using EJB 3.1

In the last post, we saw how to have scheduled processing using JBoss. The scheduling was very specific to JBoss. Let's look at how can we schedule using EJB 3.1. J2EE providers provided us with the EJB timers as alternative to threads for the timed notifications. We can schedule them like crontab in UNIX by specifying the day, hours, minutes, seconds to the service get invoked by the container.
The following example demonstrates how to use the EJB Timer service. I have created a very simple EJB application with one Stateless bean service which is being invoked by the Timer Service of the EJB.
  • Create a class with a call back method. Annotate the method with "Schedule" to make the method being called by the TimerService of EJB.
package com.test.ejb.timer;

import javax.ejb.EJB;
import javax.ejb.Schedule;
import javax.ejb.Singleton;

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

import com.test.ejb.stateless.SimpleStatelessService;

@Singleton
public class SimpleTimer {
 
     private static final Logger LOG = LoggerFactory.getLogger(SimpleTimer.class);
     
     @EJB
     SimpleStatelessService service;
     
     @Schedule(hour="*", minute="*", second="10")
     public void startTimer() {
          LOG.info("Timer started... Invoking the bean");
          service.invokeBeanMethod();
     }    
}
The attributes inside the Schedule annotation are as follows
AttributeDescriptionValue
secondOne or more seconds within a minute0 to 59, default is 0
minuteOne or more minutes within an hour0 to 59, default is 0
hourOne or more hours within a day0 to 23, default is 0
dayOfWeekOne or more days within a week0 to 7 (Sunday to Sunday) default is * (Everyday). Even Mon, Tue etc are allowed
dayOfMonthOne or more days within a month1 to 31. Default is *. (Negative values are accepted, -5 means 5th day from end of the month)
monthOne or more months within a year1 to 12. Default is *. Names of the months are also allowed like Jan, Feb etc
yearA particular calendar yearA four digit year. Default is *
  • I have created a simple stateless bean named "SimpleStatelessSerive" to be invoked by the TimerService from the callback method startTimer().
package com.test.ejb.stateless;

import javax.ejb.LocalBean;
import javax.ejb.Stateless;

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

/**
 * Session Bean implementation class SimpleStatelessService
 */
@Stateless
@LocalBean
public class SimpleStatelessService {
     private static final Logger LOG = LoggerFactory.getLogger(SimpleStatelessService.class);
    /**
     * Default constructor. 
     */
    public SimpleStatelessService() {
        LOG.info("Service Created....");
    }
    public void invokeBeanMethod()
    {
         LOG.info("Inside invokeBean method");
    }
}
  • Deploy the EJB application onto Application server. I deployed it on Jboss6. The timer service started and invoking the callback method for every 10th second of the each minute as specified in the Schedule annotation.
Glimpse of the server log is
14:28:10,010 INFO  [com.test.ejb.timer.SimpleTimer] Timer started... Invoking the bean
14:28:10,011 INFO  [com.test.ejb.stateless.SimpleStatelessService] Service Created....
14:28:10,011 INFO  [com.test.ejb.stateless.SimpleStatelessService] Inside invokeBean method
14:29:10,009 INFO  [com.test.ejb.timer.SimpleTimer] Timer started... Invoking the bean
14:29:10,010 INFO  [com.test.ejb.stateless.SimpleStatelessService] Service Created....
14:29:10,010 INFO  [com.test.ejb.stateless.SimpleStatelessService] Inside invokeBean method

We can configure multiple callback methods for scheduling and each callback can be scheduled for multiple times. Have a look at the following sample code with two callback methods configured for Scheduling.
package com.test.ejb.timer;

import javax.ejb.EJB;
import javax.ejb.Schedule;
import javax.ejb.Schedules;
import javax.ejb.Singleton;

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

import com.test.ejb.stateless.SimpleStatelessService;

@Singleton
public class SimpleTimer {
     private static final Logger LOG = LoggerFactory.getLogger(SimpleTimer.class);  
     @EJB
     SimpleStatelessService service;
     
     @Schedules( {
          @Schedule(hour="*", minute="*", second="10"),
          @Schedule(hour="*", minute="*", second="13")
     })
     public void startTimer() {
          LOG.info("Timer started... Invoking the bean");
          service.invokeBean();
     }
     
     @Schedule(minute="3")
     public void antoherTimer() {
          LOG.info("Another Timer started.. Invoking the bean");
          service.invokeBean();
     }
}
There are two schedulers configured now.
  1. The startTimer() method is being configured for two scheduled times. One is every 10th second of the minute and the other is every 13th second of the minute. 
  2. The anotherTimer() which is being called every 3rd minute of the hour.

Saturday, March 16, 2013

Scheduling in JBoss

We will look at how to schedule a process in JBoss like crontab in UNIX. This can be done in JBoss by using Schedulers. Schedulers provides a simple callback method by implementing the Schedulable interface in custom Java class. It is very easy to use this for scheduling even though we have many options like crontab in UNIX, Timers, etc because of it's easy implementation.

Lets see how to create a Scheduler in JBoss in 2 simple steps

1. Create a simple XML file for the configuration of the Scheduler. The attributes allowed in the configuration xml and their descriptions are

o    InitialStartDate : Date when the initial call is scheduled. It can be either:
o    NOW: date will be the current time plus 1 seconds
o    A number representing the milliseconds since 1/1/1970
o    Date as String able to be parsed by SimpleDateFormat 
o    InitialRepetitions : The number of times the scheduler will invoke the target's callback. If -1 then the callback will be repeated until the server is stopped.
o    StartAtStartup : A flag that determines if the Scheduler will start when it receives its startService life cycle notification. If true the Scheduler starts on its startup. If false, an explicit startScheduleoperation must be invoked on the Scheduler to begin.
o    SchedulePeriod : The interval between scheduled calls in milliseconds. This value must be bigger than 0.
o    SchedulableClass : The implementation class of  the org.jboss.varia.scheduler.Schedulable interface.
o    SchedulableArguments : A comma separated list of arguments passed to implementation class(Only primitives and String types are supported).
o    SchedulableArgumentTypes : The list of argument types passed in the above attribute.
o    SchedulableMBean : Specifies the fully qualified JMX ObjectName name of the schedulable MBean to be called. When using SchedulableMBean the SchedulableMBeanMethod must also be specified.
o    SchedulableMBeanMethod : Specifies the operation name to be called on the schedulable MBean.

<?xml version="1.0" encoding="UTF-8"?>
<server>
    <mbean code="org.jboss.varia.scheduler.Scheduler" name=":service=My-Scheduler">
        <attribute name="StartAtStartup">true</attribute>
        <attribute name="SchedulableClass">com.test.scheduler.MyScheduler</attribute>
        <attribute name="SchedulableArguments">MyScheduler</attribute>
        <attribute name="SchedulableArgumentTypes">java.lang.String</attribute>
        <attribute name="InitialStartDate">0</attribute>
        <attribute name="SchedulePeriod">5000</attribute>
        <attribute name="InitialRepetitions">-1</attribute>
    </mbean>
</server>

2. Create a class and implement Schedulable Interface. We need to implement only one method perform which takes two parameters. One is Date type, the actual date when it is being called and the other is number of times the scheduler invokes the callback method(The parameter of attribute InitialRepetitions)
package com.test.scheduler;

import java.util.Date;

import org.jboss.varia.scheduler.Schedulable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyScheduler implements Schedulable {
     
     private static final Logger LOG = LoggerFactory.getLogger(MyScheduler.class);
     private String name;
     
     public MyScheduler(String name) {
          this.name = name;
     }

     @Override
     public void perform(Date arg0, long arg1) {
          LOG.info("Started "+name);
          LOG.info("Date "+arg0+" Time "+arg1);
     }

}

That's it. Its time to deploy and run it. Deploy the class into Jboss via jar or ear project. Put the xml file in jboss deploy directory and start JBoss Server.
Once started, you will be able to see the following Log in the JBoss server log. The Scheduler calls the callback function once in every 5 seconds as defined in configuration XML.
22:21:05,066 INFO  [MyScheduler] Started MyScheduler
22:21:05,066 INFO  [MyScheduler] Date Sat Mar 16 22:21:05 IST 2013 Time -1
22:21:10,067 INFO  [MyScheduler] Started MyScheduler
22:21:10,067 INFO  [MyScheduler] Date Sat Mar 16 22:21:10 IST 2013 Time -1
22:21:15,068 INFO  [MyScheduler] Started MyScheduler
22:21:15,068 INFO  [MyScheduler] Date Sat Mar 16 22:21:15 IST 2013 Time -1

The timer will be running, until you stop the Jboss

Tuesday, March 5, 2013

Dependency Injection and Spring

When it comes to Spring, it always said that Dependency Injection is the major feature of Spring. In the last post i gave an example on how to use spring with a very basic example.

Let's see what's dependency injection is?

In Object oriented world, each and every application is collection of objects working together. In order to work together, there might me some relation (dependency in general sense) between the objects.

For example, i take an application of polymorphism in Java.

package com.test.appl;
public interface Shape 
{ 
     public abstract void draw();
}
package com.test.appl;
public class Rectangle implements Shape 
{
   @Override
   public void draw() 
   {
       System.out.println("Drawing Rectangle");
   }
}
package com.test.appl;

public class Triangle implements Shape 
{
   @Override
   public void draw() 
   {
       System.out.println("Drawing Triangle");
   }
}
It's a very old story. Let me repeat it again. Triangle and Rectangle are types of Shape. The methods of types will be called based on the object assigned to reference of Shape Class.

package com.test.appl;

public class Main 
{ 
   public static void main(String...strings)
   {
       Shape traingle = new Triangle();
       traingle.draw();
  
       Shape rectangle = new Rectangle();
       rectangle.draw();
   }
}

But there is dependency between the objects creation and assigning it to Shape references, and we do call at the same time when it was created. In short, they are tightly coupled.

We can slightly remove the dependency between Parent and its types, by creating an helper class, say ShapeHelper as defined below.

package com.test.appl;

public class ShapeHelper 
{ 
    private Shape shape;
 
    public ShapeHelper(Shape shape)
    {
        this.shape = shape;
    }
 
    public void doDraw()
    {
        shape.draw();
    }
}

ShapeHelper is the class which accepts an object of type Shape (can be Triangle or Rectangle in the current scenario . A method doDraw() is added which internally calls the draw method of Shape type. So, if we assign shape to an object of Rectangle , it calls the draw method of Rectangle(basic of runtime polymorphism). 

package com.test.appl;

public class MainWithHelper {
 
    public static void main(String...strings)
    {
        ShapeHelper sHelper = new ShapeHelper(new Triangle());
        sHelper.doDraw();
        Triangle t = new Triangle();
        sHelper = new ShapeHelper(t);
        sHelper.doDraw();
        sHelper = new ShapeHelper(new Rectangle());
        sHelper.doDraw();
    }
}

From the above example, the dependency in assigning of the objects to Shape has been removed with the help of an Helper Class. The shape is said to be injected into the ShapeHelper class.

This way of removing the dependency between the objects by injecting is called Dependency Injection (in other words. but not exactly)

Spring does this for us, with a simple xml configuration. Instantiation of objects and injecting the dependencies will be done by Spring configuration xml file(In short spring context file).

Let's write the same example in Spring with spring-context file as spring context file
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
    <bean class="com.test.appl.Triangle" id="triangle" ></bean>
    <bean class="com.test.appl.Rectangle" id="rectangle"></bean>
  
    <bean class="com.test.appl.ShapeHelper" id="helper1">
        <property name="shape" ref="triangle">
    </property></bean>
  
</beans>
I have created two different beans (one for triangle and one for rectangle). and one bean for Helper class. I injected the triangle bean into ShapeHelper. In the same way, we can inject rectangle bean.

Now, the question is how do we access them. See the below code on how to access. We need to create the ApplicationContext and then get the bean to call it's methods

package com.test.spring.appl;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.test.appl.ShapeHelper;

public class DIApplication 
{
    public static void main(String...strings)
    {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
        ShapeHelper helper = (ShapeHelper)context.getBean("helper1");
        helper.doDraw();
    }
}

The the helper will call the draw() of triangle as the injected object is triangle  To call the draw method to Rectangle, we can change the xml file rather than the actual code. That is another advantage of Spring.