Monday, November 4, 2013

Spring JMX - Expose POJOs as MBeans

Spring JMX allows you to easily expose POJOs as JMX MBeans. Even it allows the MBeans to deploy on application server which has MBean server running or can be run standalone. We can use jconsole to run the services provided by the MBean.
The configuration required to expose the POJO as Mbean is as follows. Here, MyBean is a POJO with at-least one public method.
<bean id="myMBean" class="com.test.MyBean"  />

<bean class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
   <property name="beans">
       <map>
          <entry key="bean:name=MyMBeanName" value-ref="myMBean" />
       </map>
   </property>
</bean>
MBeanExporter exposes the map of "beans" as MBeans. Here we exposed myMBean as "MyMMBeanName". This name will be shown in the jconsole. By default, all the public methods inside the POJO will be exposed as operations.
If the Spring JMX is not running under an application server, then we need a starter. Definition is as follows:
<!-- If not running on a server which has MBean server running, you must start here -->
<bean id="factory" class="org.springframework.jmx.support.MBeanServerFactoryBean" />
With the above configuration, The MBean can be accessed locally. The MBean can be exposed either using JMXJMP or RMI.
To expose using JMXJMP as follows. The default service URL to access is : service:jmx:jmxmp://localhost:9875
<bean class="org.springframework.jmx.support.ConnectorServerFactoryBean" />
To expose using RMI as follows.
<bean class="org.springframework.jmx.support.ConnectorServerFactoryBean"
    depends-on="rmiRegistry">
    <property name="objectName" value="connector:name=rmi" />
    <property name="serviceUrl"
        value="service:jmx:rmi://localhost/jndi/rmi://localhost:10099/myconnector" />
</bean>

<bean id="rmiRegistry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
    <property name="port" value="10099" />
</bean>
The complete configuration of exposing POJO using Spring JMX (With Remote access with RMI) without running an application server is as follows:
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/util 
    http://www.springframework.org/schema/util/spring-util-3.0.xsd">

    <bean id="myMBean" class="com.test.MyBean"  />

    <bean class="org.springframework.jmx.export.MBeanExporter"
       lazy-init="false">
       <property name="beans">
           <map>
           <entry key="bean:name=MyMBeanName" value-ref="myMBean" />
           </map>
        </property>
    </bean>

    <!-- If not running on a server which has MBean server running, you must start here -->
    <bean id="factory" class="org.springframework.jmx.support.MBeanServerFactoryBean" />

    <bean class="org.springframework.jmx.support.ConnectorServerFactoryBean"
        depends-on="rmiRegistry">
        <property name="objectName" value="connector:name=rmi" />
            <property name="serviceUrl"
               value="service:jmx:rmi://localhost/jndi/rmi://localhost:10099/myconnector" />
    </bean>

    <bean id="rmiRegistry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
        <property name="port" value="10099" />
    </bean>

</beans>
The POJO MyBean.java is :
package com.test;

public class MyBean {
    public void start()
    {
        System.out.println("Started");
    }
 
    public void stop()
    {
        System.out.println("Stopped");
    }
}
The Application program to start is :
package com.test.application;

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

public class Application {
   public static void main(String...args)
   {
       ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
       context.getBean("factory");
   }
}
When we run this program, it start the MBean. Connect to this using jconsole. The MBean with name "MyMBeanName" visible under MBeans Tab.

Happy Learning!!!!

Saturday, October 26, 2013

Getting started with Spring Batch 2.0

Spring batch 2.0 simpilified and improvised the batching framework. We have so many frameworks for MVC, Web, JDBC etc but batching frameworks are very rare. Spring batch is a lightweight and robust batch framework to process these big data sets. Spring offer Tasklet oriented and Chunk Oriented processing. In this post, we will see Simple Tasklet oriented processing.

Key Concepts:
  • Job - Job is a sequence of steps, each has an exit status. Execution of the next step depends on the exit status of previous step.
  • JobRepository - An interface which contains the meta data and corresponding entities of the Job. 
  • JobLauncer - Which launches a job by exposing the method to run.
  • Tasklet - An interface, can be instance of job which exposes a method called execute and returns the execution status. A tasklet will execute repeatedly until it returns FINSIHED.
Step to define (A simple job):
  • Define one job repository
  • Define one job launcher using the job repository.
  • Define Job(s) under the job launcher. Multiple jobs can be defined under one job launcher.
  • Create steps under the job. We can add multiple steps under the job with relations. By default, job launcher executes the job based on the steps defined. We can create dependency between each step. Literally, each step is a java class (Either Tasklet - a simple task or a combination of reader, writer and executiors for chunk oriented processing).
The below example shows how to define a job with single task (or step) using Tasklet.
spring-job.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/batch" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd">

  <beans:bean id="transactionManager"
    class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
  
  <beans:bean id="jobRepository"
    class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
    <beans:property name="transactionManager" ref="transactionManager" />
  </beans:bean>

  <beans:bean id="jobLauncher"
    class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
      <beans:property name="jobRepository" ref="jobRepository" />
  </beans:bean>

  <job id="sampleJob" job-repository="jobRepository">
    <step id="step1">
       <tasklet ref="sampleTasklet" />
    </step>
  </job>

  <beans:bean name="sampleTasklet" class="com.test.springbatch.SampleTasklet" />
</beans:beans>
The SampleTasklet class should be a type of Tasklet, which provides one execute. The execute method returns RepeatStatus to know the status of the task. The tasks executes multiple times if it returns CONTINUABLE otherwise stops after execution.
package com.test.springbatch;

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;

public class SampleTasklet implements Tasklet
{
    public RepeatStatus execute(StepContribution arg0, ChunkContext arg1) throws Exception
    {
        System.out.println("Do Something; ");
        // Return RepeatStatus.CONTINUABLE if something goes wrong so that it
        // repeats; Otherwise Return FINISHED to complete
        return RepeatStatus.FINISHED;
    }
}

How to run the job:
Spring provides you with CommandLineJobRunner which runs the job using the two parameters. One the spring context file and the other is the batch name.
CommandLineJobRunner.main(new String[] { "spring-batch.xml", "sampleJob" });
In the next post, we will see "Chunk Oriented processing with Spring Batch"
Happy Learning !!!!

Saturday, September 7, 2013

Spring Data - JPA

A lot of effort is required for configuration and using JPA. Spring Data JPA has reduced that to a major extent. Takes little effort to configure and easy to use. Let's look at this with an example.
The spring data dependency and hibernate dependencies using maven are as follows. (Note: All other spring core, bean, context dependencies are required along with the below dependencies)
        <!-- Spring Data JPA -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.0.2.RELEASE</version>
        </dependency>
        <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
Create a persistence xml file in META-INF file.
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
    <!--Persistence Unit for Mysql database-->
    <persistence-unit name="testMysql" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>com.test.entity.Employee</class>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
            <property name="hibernate.show_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>
Now, need to configure Spring Data - JPA using the persistent unit "testMysql"
<?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:jdbc="http://www.springframework.org/schema/jdbc"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--Following data source for Mysql-->
    <bean id="mysqltestDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.testurl}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--Following entity manager for Mysql database-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="mysqltestDataSource"/>
        <property name="persistenceUnitName" value="testMysql"/>
    </bean>

    <!--Transaction manager for both H2 and Mysql-->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    
    <jpa:repositories transaction-manager-ref="transactionManager" 
        entity-manager-factory-ref="entityManagerFactory" base-package="com.test.dao">
    </jpa:repositories>
    
</beans>
Explanation of above spring configuration Create one datasource.

  • Create one driver manager datasource named "mysqltestDataSource", by loading jdbc.properties file from the classpath using line <context:property-placeholder location="classpath:jdbc.properties"/>
  • Create entity manager factory using the datasource created and persistent unit created in persistent.xml
  • Inject entity manager factory into transaction manager. 
  • Finally configure both transaction manager and entity manager factory to set of repositories in a package (defined using base-package)
Now, create repository, an interface which extends JpaRepository inside package (defined in base-package). The typed arguments required are one entity and other is Id. In this case, entity is Employee and Id of the Employee is Long.
package com.test.dao;

import org.springframework.data.jpa.repository.JpaRepository;

import com.test.entity.Employee;

public interface EmployeeDAO extends JpaRepository<Employee, Long>
{
}
The entity is as follows
package com.test.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Table(name = "EMP")
@Entity
public class Employee
{
    private int id;
    private String name;
    private int age;
    @Id
    @Column(name = "id", unique = true, nullable = false)
    public int getId()
    {
        return id;
    }
    public void setId(int id)
    {
        this.id = id;
    }
    @Column(name = "name")
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    @Column(name = "age")
    public int getAge()
    {
        return age;
    }
    public void setAge(int age)
    {
        this.age = age;
    }
}
That's it on the configuration part. By using the repository, we can do all types of database operations for that entity. There are numberous in-built methods are provided by JpaRepository interface. Sample code for that will be
        EmployeeDAO dao = (EmployeeDAO)context.getBean("employeeDAO");
        List list = dao.findAll();
        for(Employee e : list)
        {
            //Do Something
        }

Sunday, August 18, 2013

Java New IO 2.0

The New IO is one of the features introduced in Java7. A new package java.nio has been added as part of this feature. Even though the usage wise it's same as java.io, most of the issues in java.io has been addressed. We will see the features introduced in New IO (NIO)
Path
The package java.nio.file consists of classes and interfaces Path, Paths, FileSystem, FileSystems and others. Each of represent's the file path or file system as is.
java.nio.file.Path works exactly same as java.io.File with additional features.
Path path = Paths.get("C:\\temp\\sample.txt");
System.out.println("Name Count : "+path.getNameCount());
System.out.println("Parent     : "+path.getParent());
System.out.println("Root       : "+path.getRoot());
The output will be
Name Count : 2
Parent     : C:\temp
Root       : C:\
Files
Path can also be used for deleting. There are two delete methods. One delete method can throw NoSuchFileException if the file doesn't exist.
Files.delete(path);
Where as other deletes the file if exists.
Files.deleteIfExists(path);
There are copy, move, create (Both for directories and files) with options. There are mthods to create symbolic links, temporary directories as well.
WatchService
This is the service which we can get the file change notifications like delete, update, create, change etc. WatchService API makes to receive notifications on a file or directory.
   Path path = Paths.get("C:\\Temp");
   WatchService service = path.getFileSystem().newWatchService();
   path.register(service, StandardWatchEventKinds.ENTRY_CREATE,
            StandardWatchEventKinds.ENTRY_DELETE,
            StandardWatchEventKinds.ENTRY_MODIFY);
   WatchKey watckKey = service.take();
   List<watchevent>&gt; events = watckKey.pollEvents();
   for(WatchEvent event : events)
   {
       System.out.println("Event : "+event.kind().name()+"; Context : "+event.context());
   }
The steps for creating a WatchService are
  • Create WatchService instance using path
  • Register required events (Create, delete and modify are available) on the path
  • Get the watch key and poll for the events. (For continuously watching the events, put it in infinite loop).
Happy Learning!!!

Thursday, August 15, 2013

What's in .Class file - Contd.

This is continuation of post. Now, we will see bit in detail with an example
package com.test;
public class Employee
{
     .....
     public void setEmpid(int empid)
     {
          this.empid = empid;
     }
     ....    
     public double getSalary()
     {
          return salary;
     }
     public void setSalary(double salary)
     {
          this.salary = salary;
     }
}
For example, take the above block's byte code one by one
public void setEmpid(int);
  Code:
   0:   aload_0
   1:   iload_1
   2:   putfield        #2; //Field empid:I
   5:   return
The code is pretty readable. load means loading a value. Each load is prefixed by a character ( 'i' means integer, 'd' means decimal and 'a' means an object. putfield means setting a value to other variable. Each function will have a return statement at the end. If the function has a void return type, then simple return otherwise return will be prefixed by a character. For example getSalary() method as below
public double getSalary();
  Code:
   0:   aload_0
   1:   getfield        #4; //Field salary:D
   4:   dreturn
Each and every line in the java byte code is called opcode as we discussed has a special meaning. We can find the list of all opcodes in the JVM Spec or on Wiki. Apart from the load, put, get, return, new (That we saw). There are method invocations which you will find more common. These start with invoke prefix
  • invokespecial: Used to call the instance private as well as public method (including initializations)
  • invokevirtual : Used to call a method based on the class of the object. 
  • invokestatic : Invokes a static method. 
  • so on....
Will post some more details in the next posts.