Wednesday, April 22, 2015

A detailed and (hopefully) un-biased comparison of Apache Camel and IBM Integration Bus v9.0

Over the next several months I am going to be providing a deep comparison between Apache Camel and IBM Integration Bus v9.0 (formerly IBM Message Broker). Although Camel is a light-weight integration framework and IB9 a full featured ESB, both use Enterprise Integration Patterns to reduce the complexity and cost when it comes to integrating heterogenous systems.

Before I start I will mention a few things...

I've been using Apache Camel since version 1.5.4 on R&D and production-grade systems in the Defense and Aerospace industry. I've also have experience using other Apache products such as Karaf, ServiceMix, ActiveMQ, and many other Enterprise Java projects such as Maven, Spring, JPA, the list goes on.... Only until recently I began using IBM products in a large IT organization. (e.g. Integration Bus v9, IBM MQ). Thus, my experience on IBM products is still fairly new. So you can say that I have a lot of background in Enterprise Java Development in the open source area and less background in IBM's product suite. So my comparison will be coming from the background of a Java developer.

I have also been to many Apache Camel conferences and training. I have also been in IB9 training and also attend IBM developer conferences as well. So there will be detailed thoughts on things like support, training and documentation.

Needless to say this blog series will provide a very detailed comparison of Camel and IB9, occasionally including other projects (mentioned above). Since I am fan of open source and Java development I will try to be as un-biased as possible, however, I will often share my likes/dislikes about each.

Before I begin let me be clear that this blog series is meant to provide:

  • A detailed comparison of the features in IB9 and Camel, including related projects such as IBM MQ, Open Source Products (e.g. ServiceMix, ActiveMQ, Spring, JPA, etc..).
  • My thoughts and subjective opinions on things I like and dislike about each product. Hopefully this will be un-biased.
And I want to be crystal clear that it is NOT meant to provide:

  • A guide which you should base your decision when choosing Camel or IB9. It is recommended you evaluate both products yourself.
  • A recommendation or conclusion on which product is better. Both have pros and cons.
  • A flame war between the two products. IBM does a great job in many of its products, as does Apache Camel community. 

I hope to make a blog post at least once a month, so stay tuned...

Tuesday, April 14, 2015

Spring Property Example

This is a simple example showing how to set properties on Spring @Component and @Bean using @Value and @PropertySource, respectively. The source code for this example is located on github https://github.com/jamie3/spring-property-config.

First create the properties file.

Next create a Java bean.


package spring.property.example;

public class MyBean {

 String beanProperty;
}


Next create a Java component.


package spring.property.example;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class MyComponent {

 @Value("${componentProperty}")
 String componentProperty;
 
 
}


Next create a Java configuration. As you can see the @PropertySource loads the properties into the Environment class which is then used by the myBean() method to set properties on the bean. This is useful when you have objects from 3rd party jars and want to set properties on them.

The propertyPlaceHolderConfigurer() method is the equivalent of from Spring's XML. Since we are using annotation-based @Configuration we must create a static instance of the PropertyPlaceHolderConfigurer class such that it will perform the automatic injection of the properties into our @Component that contains @Value.
package spring.property.example;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.Environment;

@Configuration
@ComponentScan("spring.property.example")
@PropertySource("example.properties")
public class AppConfig {

 /**
  * Uses the environment to inject the property into the beans that do not have the @Value attribute
  * 
  * @param environment
  * @return
  */
 @Bean
 public MyBean myBean(Environment environment) {
  MyBean bean = new MyBean();
  bean.beanProperty = environment.getProperty("beanProperty");
  return bean;
 }
 
 /**
  * Loads the properties into the beans using the @Value attribute
  * 
  * @return
  */
 @Bean
 public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(Environment environment) {
  PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
  propertySourcesPlaceholderConfigurer.setEnvironment(environment);
  return propertySourcesPlaceholderConfigurer;
 }
}


Finally the main class which creates the Spring Context.


package spring.property.example;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {

 private Main() {
  
 }
 
 public static void main(String[] args) {
  
  Object obj = new Object();
  AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  try {
   
   MyBean myBean = context.getBean(MyBean.class);
   System.out.println("MyBean.beanProperty = " + myBean.beanProperty);
   
   MyComponent myComponent = context.getBean(MyComponent.class);
   System.out.println("MyComponent.componentProperty = " + myComponent.componentProperty);
   
   synchronized (obj) {
    obj.wait();
   }
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } finally {
   context.close();
  }
 }
}

Tuesday, April 7, 2015

Message Driven Bean in WebSphere 8.0

This is a quick blog post on how to create and deploy a Message Driven Bean on WebSphere 8.0 using Maven 3. Code for this can be found at https://github.com/jamie3/websphere-mdb.

Project structure


I created the following project structure using maven

+ websphere-mdb
    + websphere-mdb-ear
    + websphere-mdb-ejb
    + websphere-mdb-jar

Top Level POM

websphere-mdb is the top level project which contains the follow modules:
  • websphere-mdb-ear - EAR project
  • websphere-mdb-ejb - EJB project
  • websphere-mdb-jar - 3rd party source code which the EJB uses


I set the compiler level to 1.6 since we are deploying on WAS 8.0.


<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/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 
 <groupId>com.github.jamie3</groupId>
 <artifactId>websphere-mdb</artifactId>
 <version>1.0.0</version>
 <packaging>pom</packaging>
 
 <modules>
  <module>websphere-mdb-jar</module>
  <module>websphere-mdb-ejb</module>
  <module>websphere-mdb-ear</module>
 </modules>
  
 <build>
  <plugins>
   <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
     <source>1.6</source>
     <target>1.6</target>
    </configuration>
   </plugin>
  </plugins>
 </build> 
  
</project>


EJB Module

The EJB Module uses the maven-ejb-plugin and also has a a dependency on jms and my jar file. I also used the JBOSS repository to load the jms dependency.

The ejb pom can be found at https://github.com/jamie3/websphere-mdb/blob/master/websphere-mdb-ejb/pom.xml.

In the META-INF folder of the EJB I added the ibm-ejb-jar-bnd.xml file which is loaded by IBM WebSphere Application Server during deployment of the EAR.


<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/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <artifactId>websphere-mdb-ejb</artifactId>
 <packaging>ejb</packaging>

 <parent>
  <groupId>com.github.jamie3</groupId>
  <artifactId>websphere-mdb</artifactId>
  <version>1.0.0</version>
 </parent>

 <dependencies>
  <dependency>
   <groupId>com.github.jamie3</groupId>
   <artifactId>websphere-mdb-jar</artifactId>
   <version>1.0.0</version>
  </dependency>
  <dependency>
   <groupId>javax.ejb</groupId>
   <artifactId>ejb-api</artifactId>
   <version>3.0</version>
   <scope>provided</scope>
  </dependency>
  <dependency>
   <groupId>javax.jms</groupId>
   <artifactId>jms</artifactId>
   <version>1.1</version>
   <scope>provided</scope>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-ejb-plugin</artifactId>
    <version>2.5</version>
    <configuration>
     <ejbVersion>3.1</ejbVersion>
     <generateClient>false</generateClient>
     <archive>
      <manifest>
       <addClasspath>false</addClasspath>
      </manifest>
     </archive>
    </configuration>
   </plugin>
  </plugins>
 </build>


 <repositories>
  <repository>
   <id>repository.jboss.org-public</id>
   <name>JBoss.org Maven repository</name>
   <url>https://repository.jboss.org/nexus/content/groups/public</url>
  </repository>
 </repositories>

</project>


Create Message Driven Bean

In the EJB module I added a class as my Message Driven Bean.


package ejb;

import jar.Echo;

import javax.annotation.PostConstruct;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;

/**
 * Session Bean implementation class MySessionBean
 */
@MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") }, mappedName = "jms/SomeQueue")
public class MyMDB implements javax.jms.MessageListener {

 Echo echo;
 
    /**
     * Default constructor. 
     */
    public MyMDB() {
        // TODO Auto-generated constructor stub
     
    }

    @PostConstruct
    public void init() {
     System.out.println("initializing ejb");
     echo = new Echo();
    }

 @Override
 public void onMessage(Message message) {
  // TODO Auto-generated method stub
  TextMessage text = (TextMessage)message;
     try {
      String msg = text.getText();
   echo.echo("Message from JMS: " + text.getText());
  } catch (JMSException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}


JAR Module

The JAR Module contains a simple class which is used by my EJB.


package jar;

public class Echo {

 public void echo(String text) {
  System.out.println(text);
 }
}

The pom for the jar module can be found here https://github.com/jamie3/websphere-mdb/blob/master/websphere-mdb-jar/pom.xml.

EAR Module


Finally the EAR module uses the maven-ear-plugin to add the JAR and EJB as EAR modules. All third party dependencies are packed into the lib folder.



<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/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <parent>
  <groupId>com.github.jamie3</groupId>
  <version>1.0.0</version>
  <artifactId>websphere-mdb</artifactId>
 </parent>
 
 <artifactId>websphere-mdb-ear</artifactId>
 <packaging>ear</packaging>

 <dependencies>
  <dependency>
   <groupId>com.github.jamie3</groupId>
   <artifactId>websphere-mdb-ejb</artifactId>
   <version>1.0.0</version>
   <type>ejb</type>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <artifactId>maven-ear-plugin</artifactId>
    <version>2.10</version>
    <configuration>
     <version>6</version>
     <defaultLibBundleDir>lib</defaultLibBundleDir>
     <modules>
      <ejbModule>
       <groupId>com.github.jamie3</groupId>
       <artifactId>websphere-mdb-ejb</artifactId>
      </ejbModule>
      <jarModule>
       <groupId>com.github.jamie3</groupId>
       <artifactId>websphere-mdb-jar</artifactId>
      </jarModule>
     </modules>
    </configuration>
   </plugin>
  </plugins>
 </build>
 
 <repositories>
  <repository>
   <id>repository.jboss.org-public</id>
   <name>JBoss.org Maven repository</name>
   <url>https://repository.jboss.org/nexus/content/groups/public</url>
  </repository>
 </repositories>
</project>