Archive for 2012
Configuring IBM MQ in JBoss
In today's post I will explain how to install the WebSphere MQ resource adapter on JBoss.
Installing WebSphere MQ resource adapter:
To install WebSphere MQ resource adapter, copy the file wmq.jmsra.rar (from installation directory) to the server's deploy directory, for example <install path>/server/default/deploy The resource adapter will be automatically picked up by the server.
Installing the WebSphere MQ Extended Transactional Client:
The WebSphere MQ Extended transactional client lets you use XA distributed transactions with CLIENT mode connections to a WebSphere MQ queue manager. To install it on JBoss, copy the file com.ibm.mqetclient.jar ( from installation directory ) to the server lib directory, for example <install path>/server/default/lib.
Configuring the resource adapter for your application:
The WebSphere MQ resource adapter lets you define a number of global properties. Resource definitions for outbound JCA flows are defined in a JBoss -ds.xml file named wmq.jmsra-ds.xml. The outline form of this file:
As can be seen above JCA connection factories are defined in the <tx-connection-factory> element and JMS queues and topics are defined as JCA administered object mbeans.
A complete example for our sample application defining two queues - inbound and outbound is given below:
The place holder properties are defined in the JBoss start script as:
-Dchannel=MQTEST -DhostName=localhost -DqueueManager=TST_MGR
Configuring inbound message delivery:
Message delivery to a Message-Driven Enterprise JavaBean (MDB) is configured using a JBoss-specific file named jboss.xml, located in the MDB .ear file. The contents of this file will vary, but will be of the form:
jboss.xml:
The DestinationType and Name properties must be specified. Other properties are optional, and if omitted, take on their default values.
A simple MDB definition for the inbound message is shown below:
A plain java class to send message to the output queue is shown below.
That's all.
Installing WebSphere MQ resource adapter:
To install WebSphere MQ resource adapter, copy the file wmq.jmsra.rar (from installation directory) to the server's deploy directory, for example <install path>/server/default/deploy The resource adapter will be automatically picked up by the server.
Installing the WebSphere MQ Extended Transactional Client:
The WebSphere MQ Extended transactional client lets you use XA distributed transactions with CLIENT mode connections to a WebSphere MQ queue manager. To install it on JBoss, copy the file com.ibm.mqetclient.jar ( from installation directory ) to the server lib directory, for example <install path>/server/default/lib.
Configuring the resource adapter for your application:
The WebSphere MQ resource adapter lets you define a number of global properties. Resource definitions for outbound JCA flows are defined in a JBoss -ds.xml file named wmq.jmsra-ds.xml. The outline form of this file:
As can be seen above JCA connection factories are defined in the <tx-connection-factory> element and JMS queues and topics are defined as JCA administered object mbeans.
A complete example for our sample application defining two queues - inbound and outbound is given below:
jms/MyAppConnectionFactory wmq.jmsra.rar true javax.jms.QueueConnectionFactory 8 36 ${channel} ${hostName} 1414 ${queueManager} CLIENT munish JmsXARealm jms/IncomingQueue jboss.jca:name='wmq.jmsra.rar',service=RARDeployment javax.jms.Queue baseQueueManagerName=${queueManager} baseQueueName=MY.APP.INBOUND.QUEUE jms/OutgoingQueue jboss.jca:name='wmq.jmsra.rar',service=RARDeployment javax.jms.Queue baseQueueManagerName=${queueManager} baseQueueName=MY.APP.OUTBOUND.QUEUE
The place holder properties are defined in the JBoss start script as:
-Dchannel=MQTEST -DhostName=localhost -DqueueManager=TST_MGR
Configuring inbound message delivery:
Message delivery to a Message-Driven Enterprise JavaBean (MDB) is configured using a JBoss-specific file named jboss.xml, located in the MDB .ear file. The contents of this file will vary, but will be of the form:
jboss.xml:
MyMessageBean DestinationType javax.jms.Queue destination MY.APP.INBOUND.QUEUE channel ${channel} hostName ${hostName} port 1414 queueManager ${queueManager} transportType CLIENT username munish wmq.jmsra.rar
The DestinationType and Name properties must be specified. Other properties are optional, and if omitted, take on their default values.
A simple MDB definition for the inbound message is shown below:
/** * This message driven bean is used to collect asynchronously received messages. * * @author Munish Gogna */ @MessageDriven(mappedName = "jms/IncomingQueue") public final class MyMessageBean implements javax.jms.MessageListener { private static final org.apache.log4j.Logger LOGGER = org.apache.log4j.Logger.getLogger(MyMessageBean.class); public void onMessage(final javax.jms.Message message) { LOGGER.info("Received message: " + message); // TODO - do processing with the message here } }
A plain java class to send message to the output queue is shown below.
/** * This class is used to send text messages to a queue. * * @author Munish Gogna */ public final class MessageSender { private static final org.apache.log4j.Logger LOGGER = org.apache.log4j.Logger.getLogger(MessageSender.class); /** * A coarse-grained method, nothing fancy. In actual applications please re factor the code and * handle the exceptions properly. * * @throws Exception */ public void send(final String message) throws Exception { if (message == null) { throw new IllegalArgumentException("Parameter message cannot be null"); } javax.jms.QueueConnection connection = null; javax.jms.Session session = null; try { javax.naming.Context fContext = new javax.naming.InitialContext(); javax.jms.QueueConnectionFactory fConnectionFactory = (javax.jms.QueueConnectionFactory) fContext .lookup("java:jms/MyAppConnectionFactory"); connection = fConnectionFactory.createQueueConnection(); session = connection.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE); final javax.naming.Context jndiContext = new javax.naming.InitialContext(); final javax.jms.Destination destination = (javax.jms.Destination) jndiContext.lookup("jms/OutgoingQueue"); final javax.jms.MessageProducer messageProducer = session.createProducer(destination); final javax.jms.TextMessage textMessage = session.createTextMessage(message); messageProducer.send(textMessage); messageProducer.close(); } catch (Exception nex) { throw nex; } finally { if (session != null) { try { session.close(); } catch (JMSException e) { LOGGER.error("Failed to close JMS session", e); } } if (connection != null) { try { connection.close(); } catch (JMSException e) { LOGGER.error("Failed to close JMS connection", e); } } } } }A utilty called RFHUTILC.EXE can be used to connect to remote queues.
That's all.
Saving development time with local EntityManager in JPA
In almost all real world projects (non Spring + We are not considering Arquillian or any similar framework) where you are using JPA (Hibernate implementation), the data source binding happens by JNDI and the services are provided by EJBs, which means to test your entities for any CRUD operation you have to deploy the bundle (ear, ejb or war) into the application server which adds time to your development efforts each time you make any change.
So in this post we will see how we can temporarily inject entity manager into your business class so that you can test all the operations you want to perform on entities without deploying the application or restarting server quite often.
persistence.xml: The configuration for entity managers both inside an application server and in a standalone application reside in a persistence archive. In the next section we focus on standalone configuration.
Let's try one sample example:
Hibernate: select entity0_.id as id0_, entity0_.value as value0_ from Entity entity0_
Before Entities: []
Hibernate: select entity0_.id as id0_0_, entity0_.value as value0_0_ from Entity entity0_ where entity0_.id=?
Hibernate: insert into Entity (value, id) values (?, ?)
Hibernate: select entity0_.id as id0_, entity0_.value as value0_ from Entity entity0_
After Entities: [Id:1, Value:my first value]
persistence.xml: The configuration for entity managers both inside an application server and in a standalone application reside in a persistence archive. In the next section we focus on standalone configuration.
Please Note:org.hibernate.ejb.HibernatePersistence com.gognamunish.test.Entity
- The database dialect we have chosen is MySQL for obvious reasons.
- Persistence unit has name test_unit and the type is RESOURCE_LOCAL and not JTA.
- com.gognamunish.test.Entity is the entity which we want to test later.
- As we are running without a JNDI available datasource, we must specify JDBC connections with Hibernate specific properties
EntityManagerFactory factory ; factory = Persistence.createEntityManagerFactory("test_unit"); EntityManager manager = factory.createEntityManager();That's all you need , after obtaining the reference focus only on your entity and the operation you want to perform on it.
Let's try one sample example:
/* Sample Entity class */ @javax.persistence.Entity @Table(name = "Entity") public class Entity { @Id private Long id; @Column private String value; }
package com.gognamunish.test; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; /** * Sample Test - nothing fancy. * * @author Munish Gogna * */ public class LocalEntityManager { static EntityManager manager; static { EntityManagerFactory factory = Persistence .createEntityManagerFactory("test_unit"); manager = factory.createEntityManager(); } public static void main(String[] args) { System.out.println("Before Entities: " + getEntities()); manager.getTransaction().begin(); Entity entity = new Entity(); entity.setId(1l); entity.setValue("my first value"); saveOrUpdate(entity); manager.getTransaction().commit(); System.out.println("After Entities: " + getEntities()); } private static Entity saveOrUpdate(Entity entity) { return manager.merge(entity); } @SuppressWarnings("unchecked") private static List<Entity> getEntities() { return manager.createQuery("from Entity").getResultList(); } }LOGS:
Hibernate: select entity0_.id as id0_, entity0_.value as value0_ from Entity entity0_
Before Entities: []
Hibernate: select entity0_.id as id0_0_, entity0_.value as value0_0_ from Entity entity0_ where entity0_.id=?
Hibernate: insert into Entity (value, id) values (?, ?)
Hibernate: select entity0_.id as id0_, entity0_.value as value0_ from Entity entity0_
After Entities: [Id:1, Value:my first value]
Reverse a String in Java
One of the frequently asked questions in interviews, let's try few ways available in JDK to reverse a string:
import java.util.Stack; public class StringReverse { public static String reverse1(String s) { int length = s.length(); if (length <= 1) return s; String left = s.substring(0, length / 2); String right = s.substring(length / 2, length); return reverse1(right) + reverse1(left); } public static String reverse2(String s) { int length = s.length(); String reverse = ""; for (int i = 0; i < length; i++) reverse = s.charAt(i) + reverse; return reverse; } public static String reverse3(String s) { char[] array = s.toCharArray(); String reverse = ""; for (int i = array.length - 1; i >= 0; i--) reverse += array[i]; return reverse; } public static String reverse4(String s) { return new StringBuffer(s).reverse().toString(); } public static String reverse5(String orig) { char[] s = orig.toCharArray(); int n = s.length - 1; int halfLength = n / 2; for (int i = 0; i <= halfLength; i++) { char temp = s[i]; s[i] = s[n - i]; s[n - i] = temp; } return new String(s); } public static String reverse6(String s) { char[] str = s.toCharArray(); int begin = 0; int end = s.length() - 1; while (begin < end) { str[begin] = (char) (str[begin] ^ str[end]); str[end] = (char) (str[begin] ^ str[end]); str[begin] = (char) (str[end] ^ str[begin]); begin++; end--; } return new String(str); } public static String reverse7(String s) { char[] str = s.toCharArray(); Stack<Character> stack = new Stack<Character>(); for (int i = 0; i < str.length; i++) stack.push(str[i]); String reversed = ""; for (int i = 0; i < str.length; i++) reversed += stack.pop(); return reversed; } }Feel free to suggest other ways if you have.
Merging PDFs while retaining the fill able forms inside them
My previous post was about merging the PDF files into single file using PDFBox, the limitation of that approach was if you had fill able form inside any PDF file it was lost, to over come that issue here is an updated version of the same post using iText library.
The iText jar can be downloaded here
Thanks.
import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Set; import com.lowagie.text.pdf.AcroFields; import com.lowagie.text.pdf.PdfCopyFields; import com.lowagie.text.pdf.PdfReader; /** * Merges the PDF files while retaining the fillable forms within them. It also * renames form field (to avoid conflicts) which can have an impact if form is * submitted to server but for printing purpose should be OK. * * @author Munish Gogna * */ public class PDFMerge { private static int counter = 0; public static void merge(List<InputStream> sourcePDFs, OutputStream targetPDF) throws Exception { if (sourcePDFs != null && targetPDF != null) { PdfCopyFields copy = new PdfCopyFields(targetPDF); for (InputStream stream : sourcePDFs) { PdfReader pdfReader = new PdfReader(stream); renameFields(pdfReader.getAcroFields()); copy.addDocument(pdfReader); stream.close(); } copy.close(); } } private static void renameFields(AcroFields fields) { Set<String> fieldNames = fields.getFields().keySet(); String prepend = String.format("_%d.", counter++); for (String fieldName : fieldNames) { fields.renameField(fieldName, prepend + fieldName); } } public static void main(String[] args) { try { List<InputStream> pdfs = new ArrayList<InputStream>(); pdfs .add(new URL( "http://thewebjockeys.com/TheWebJockeys/Fillable_PDF_Sample_from_TheWebJockeys_vC5.pdf") .openStream()); pdfs .add(new URL( "http://help.adobe.com/en_US/Acrobat/9.0/Samples/interactiveform_enabled.pdf") .openStream()); OutputStream output = new FileOutputStream("merged.pdf"); merge(pdfs, output); } catch (Exception e) { e.printStackTrace(); } } }
The iText jar can be downloaded here
Thanks.