Pages

Monday, October 28, 2013

Bundling single or multiple ear using assembly plug-in - How to use maven dependency set

Our application consists of multiple EAR's online, batch etc.
We faced a situation where we need to bundle multiple ear's, db scripts and property
files to make a delivery. I searched for creating an assembly descriptor but could not
find exact details on how to do it. After couple of days of browsing and trial and
error I figured out a way.

For example your application contains appl-1-ear (version - 1.0),appl-2-ear (version 2.0),
db-scripts.zip (0.0.1), properties.zip (0.0.10). You need to create a pom file which contains the
versions you want to include in your final delivery.

The advantage of this approach is, you can deliver your compoents and just declare the versions in
your delivery pom to create a final delivery. Even if it is not multiple ear's, but you have to
bundle various versions of db scripts with different versions of application this approach will
come handy.

You need to create a pom file something like below. Here declaring the type as ear is important because
by default maven searches for Jar extension for the given version number.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.ravi</groupId>
    <artifactId>appl-delivery</artifactId>
    <version>0.0.2-SNAPSHOT</version>
    <packaging>pom</packaging>
<dependencies>
    <dependency>
<groupId>com.ravi.presentation</groupId>
<artifactId>appl-1-ear</artifactId>
<version>1.o</version>
<type>ear</type>
    </dependency>
   <dependency>
<groupId>com.ravi.batch</groupId>
<artifactId>appl-2-ear</artifactId>
<version>1.0</version>
<type>ear</type>
    </dependency>
<dependency>
<groupId>com.ravi.properties</groupId>
<artifactId>properties</artifactId>
<version>0.0.10</version>
<classifier>archive</classifier>
<type>zip</type>
</dependency>
<dependency>
<groupId>com.ravi.dbscripts</groupId>
<artifactId>db-scripts</artifactId>
<version>0.0.1</version>
<classifier>archive</classifier>
<type>zip</type>
</dependency>
  </dependencies>
 <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.2-beta-2</version>
                <executions>
                    <execution>
                        <id>bundle-project-sources</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <configuration>
                            <descriptors>
<descriptor>assembly.xml</descriptor>
 </descriptors>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

your assembly descriptor will look something like this

<assembly>
    <id>archive</id>
    <formats>
        <format>tar.gz</format>
    </formats>
    <dependencySets>
    <dependencySet>
        <includes>
            <include>com.ravi.batch:*:EAR</include>
<include>com.ravi.presentation:*:EAR</include>
<include>com.ravi.properties:*:zip</include>
<include>com.ravi.dbscripts:*:zip</include>
        </includes>
        <!--<useProjectArtifact>true</useProjectArtifact>-->
        <outputDirectory>bin</outputDirectory>
<outputFileNameMapping>
                ${artifact.artifactId}.${artifact.extension}
         </outputFileNameMapping>
        <unpack>false</unpack>
    </dependencySet>  
</dependencySets>
</assembly>

Monday, October 21, 2013

Step by step guide to create a Spring Message Driven Pojo - Spring MDP

In your spring application you may have a requirement to listen to the incoming messages. This can be easily achieved by Spring MDP (Spring Message Driven Pojo). When you are doing for the first time, you will face few issues and it will take some time. I went through that problem so thought of documenting it.

Create a sample message listener class which implements the MessageListener interface. This interface has the onMessage method which has to be implemented by the class. Here it is just simply prints a message to the console.

import javax.jms.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class SampleMessageListener implements MessageListener {
 private static final Logger logger = LoggerFactory
   .getLogger(SampleMessageListener .class);
 @Autowired
 MessageHandler Handler;
 public void onMessage(Message message) {

  logger.info("Message received ..");
  try {
System.out.println("Message received..");
  } catch (Exception ccEx) {
   logger.error("Processing  failed :" + ccEx);
   throw new RuntimeException(ccEx);
  }
 }
}

Next the spring context file.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

xmlns:p="http://www.springframework.org/schema/p"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:jms="http://www.springframework.org/schema/jms" 
 xmlns:jee="http://www.springframework.org/schema/jee" 
 xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/jms
                           http://www.springframework.org/schema/jms/spring-jms.xsd
                           http://www.springframework.org/schema/jee
                           http://www.springframework.org/schema/jee/spring-jee-3.0.xsd>

 <context:component-scan base-package="com.ravi.jms" />
 <context:annotation-config />

 <!-- JMS config -->
 <bean id="sampleMessageListener" class="com.ravi.jms.SampleMessageListener" />
 <jee:jndi-lookup id="sampleConnectionFactory" resource-ref="true" jndi-name="jms/Sample_CF" />
 <jee:jndi-lookup id="sampleQueueName" resource-ref="true" jndi-name="jms/sampleIncomingQ" />

 <bean id="sampleMessageListenerContainer"
  class="org.springframework.jms.listener.DefaultMessageListenerContainer">
  <property name="connectionFactory" ref="sampleConnectionFactory" />
  <property name="destination" ref="jms_acknack_queueName" />
  <property name="messageListener" ref="recievedAckNackMessageListener" />
  <property name="sessionTransacted"  value="true"></property>
  <property name="recoveryInterval" value="300000"></property>
 </bean>
</beans>

Web.xml of the application. The resources (Queue connection factory and queue) has to be defined here.

<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 <display-name>Sample Application</display-name>
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/applicationContext.xml</param-value>
 </context-param>
 
 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
 <servlet>
  <servlet-name>MyDispatcherServlet</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>MyDispatcherServlet</servlet-name>
  <url-pattern>*.do</url-pattern>
 </servlet-mapping>
 
 <resource-ref id="ResourceRef_001">
  <description>The QueueConnectionFactory for the service</description>
  <res-ref-name>jms/Sample_CF</res-ref-name>
  <res-type>javax.jms.QueueConnectionFactory</res-type>
  <res-auth>Container</res-auth>
  <res-sharing-scope>Shareable</res-sharing-scope>
 </resource-ref>
 
 <resource-ref id="ResourceRef_002">
  <description>The Queue for the service</description>
  <res-ref-name>jms/sampleIncomingQ</res-ref-name>
  <res-type>javax.jms.Queue</res-type>
  <res-auth>Container</res-auth>
  <res-sharing-scope>Shareable</res-sharing-scope>
 </resource-ref>
</web-app>


If you are deploying in websphere you need the ibm-bnd.xmi file also.

<?xml version="1.0" encoding="UTF-8"?>
<webappbnd:WebAppBinding xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
xmlns:webappbnd="webappbnd.xmi" xmi:id="WebAppBinding_1238927070062"
virtualHostName="default_host">

  <webapp href="WEB-INF/web.xml#WebApp_ID"/>

  <resRefBindings xmi:id="ResourceRefBinding_001" jndiName="jms/Sample_CF">
    <bindingResourceRef href="WEB-INF/web.xml#ResourceRef_001"/>
  </resRefBindings>

  <resRefBindings xmi:id="ResourceRefBinding_002" jndiName="jms/sampleIncomingQ">
    <bindingResourceRef href="WEB-INF/web.xml#ResourceRef_002"/>
  </resRefBindings>  
</webappbnd:WebAppBinding>

Spring - Eclipse - Mavens - Issues and How to Resolve them

Issue - Spring Application not loading/starting in Eclipse Tomcat

Sometimes for strange reason, your Spring application won't be loaded by Tomcat. If you start the tomcat server, instead of loading the spring context file configured in the web.xml, the server just starts and you wont see anything specific to your application in the log file.

The issue is because of Maven configuration. Just select the web project, right click and then Select Maven. In Maven you will find the option to Update project. Just do that. Now the application should be starting like a charm in Eclipse. Select the project > Maven > Update Project


Issue - Where Eclipse keeps/explodes the Web application

It is very handy to know when you install the application on the Tomcat running in Eclipse, where exactly it
explodes the war file. Some times, you deployed the application but still the application not starting properly or you are facing some weird issues during the start-up like class not found exception when you know for sure the jar is there in the class path. Sometimes it is problem with exploding the application. You can go and see what is the problem in exploding the application.

Double click on the server where you installed the application and it should bring the overview screen of the server. There you can see the server path something like this .metadata\.plugins\org.eclipse.wst.server.core\tmp1. You should append your work space location. For example if your workspace is c:\1\workspace then the server explodes your application content in c:\1\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps. You can see your application folder in this location. You can go and see in your application lib directory you have the jar file you are looking for.

Sunday, October 13, 2013

Step by step guide to setup Cassandra and cqlsh in windows

Today I started to play with Cassandra by installing it in my windows machine. Though the instructions in the cassandra download site is clear and precise, I faced few issues in setting it up. So I thought of sharing the information for fellow developers.

Step 1: Download Cassandra from http://cassandra.apache.org/download/. The current latest version is 2.0.1. It is a tar.gz file. Download and extract it in some location in your machine. For example C:\3\apache-cassandra-2.0.1

Step 2: You can start cassandra server by calling cassandra.bat available with in the bin directory. It should startup the Cassandra server (Note: You should have Java home environment variable set to start the server)

Step 3: Now to interact with Cassandra database you need the cqlsh interactive command tool. Here is the small twist. There is none in the cassandra download package. So there is a work around we should do before adding records to the database.

3a) Download python from the below location http://www.python.org/download/releases/. Be careful here. Though the python latest version is 3.x, there is problem with installing thrift library with the latest version of Python. So download and install 2.7 version of Python.
3b) Install Thrift library by downloading it from the below location http://pypi.python.org/pypi/thrift. Install thrift module by executing the below command python setup.py install

If the python version not supported you may get this error . Revert back to version 2.7.x version of Python and then it should run like a charm

Step 4 : Now you should install cql module for python which is available with in cassandra download.  The setup.py file is available in the below location C:\3\apache-cassandra-2.0.1\pylib. Again run the command python setup.py install. 

Step 5:  Now you can run the command python cqlsh localhost 9160 and it will start the cql interactive command.  Here you can start issuing the commands llike keyspace creation etc.

CREATE KEYSPACE mykeyspace WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };

CREATE TABLE users (user_id int PRIMARY KEY,  fname text,  lname text);

INSERT INTO users (user_id,  fname, lname) VALUES (1745, 'john', 'smith');
INSERT INTO users (user_id,  fname, lname)  VALUES (1744, 'john', 'doe');
INSERT INTO users (user_id,  fname, lname)  VALUES (1746, 'john', 'smith');


 
Blogger Templates