spring Posts

Error at Spring Roo : Rebuild Project, No Crosscutting Model Available

Found this weird error on my STS, when im trying to Push-In an AspectJ class.

It’s actually very easy to fix this, you only need to Clean and Rebuild the project. After you do it, you can easily Push In your AspectJ into your Java Code. (H)

A Client Server Application using Spring HTTP Invoker

Right now, im trying to create a simple client-server application using spring HTTP invoker. One major advantage using Spring Http Invoker is that instead of the custom serialization found in Hessian and Burlap, HTTP invoker uses Java serialization — just like RMI. Applications can rely on full serialization power, as long as all transferred objects properly follow Java serialization rules (implementing the java.io.Serializable marker interface and properly defining serialVersionUID if necessary).

Because of the nature of HTTP invoker (which is available only in Spring), both the client side and the server side need to be based on Spring — and on Java in the first place because of the use of Java serialization. In contrast to Hessian and Burlap, there is no option for cross-platform remoting. HTTP invoker is clearly dedicated to powerful and seamless Java-to-Java remoting.

Okay, let me show you my client side’s code, first is a very simple bean.

package com.edw.bean;

import java.io.Serializable;
import java.math.BigDecimal;

public class BeanBego implements Serializable {
    private String nama;
    private int usia;
    private double gaji;
    private float x;
    private float y;
    private BigDecimal z;

    public String getNama() {
        return nama;
    }

    public void setNama(String nama) {
        this.nama = nama;
    }

    public int getUsia() {
        return usia;
    }

    // other setters and getters

next is an interface to connect with the server side application.

package com.edw.service;

public interface TestService {

    void doNothing();

    String doSomething(String something);
    String doSomething(Object something);
}

and this is my client’s side Spring configuration. Take a look at line 6, it is my server side’s application location. And on line 7, is my interface class.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
    <bean id="testHttpInvoker" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
        <property name="serviceUrl" value="http://localhost:8084/SpringHttpInvokerServer/testService.service"/>
        <property name="serviceInterface" value="com.edw.service.TestService"/>
    </bean>
</beans>

and this is my application’s main class,

package com.edw.spring.main;

import com.edw.bean.BeanBego;
import com.edw.service.TestService;
import java.math.BigDecimal;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    private Logger logger = Logger.getLogger(this.getClass());

    public Main() throws Exception {
    }

    private void execute() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        TestService testService = (TestService) applicationContext.getBean("testHttpInvoker");

        BeanBego beanBego = new BeanBego();
        beanBego.setGaji(2000000000d);
        beanBego.setUsia(500);
        beanBego.setX(500000000f);
        beanBego.setY(6000000f);
        beanBego.setZ(new BigDecimal(Double.MAX_VALUE));

        String testString = "";
        for (int i = 0; i < 2000; i++) {
            testString += " " + i + " pepe ";
        }

        beanBego.setNama(testString);

        logger.debug(testService.doSomething(beanBego));
    }

    public static void main(String[] args) throws Exception {
        Main main = new Main();
        main.execute();
    }
}

and now lets create the server side’s application, btw im using Apache Tomcat as my web server, first i copy my BeanBego class and TestService interface from client’s side to the server side. After that, i create the implementation of TestService interface,

package com.edw.service;

import com.edw.bean.BeanBego;
import org.apache.log4j.Logger;

public class TestServiceImpl implements TestService {

    private Logger logger = Logger.getLogger(this.getClass());

    public void doNothing() {
        logger.debug("im doing nothing");
    }

    public String doSomething(String something) {
        logger.debug("im doing something");
        return "connect successfully";
    }

    public String doSomething(Object something) {
        logger.debug("im doing something");

        if(something instanceof BeanBego)
            return ((BeanBego)something).getGaji()+"";
        return "not a BeanBego instance";
    }
   
}

next step is registering your class to your main Spring configuration, remember to named it “remoting-servlet.xml”.

<?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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

    <bean id="testService" class="com.edw.service.TestServiceImpl"/>

    <bean id="testHttpInvoker" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
        <property name="service">
            <ref bean="testService"/>
        </property>
        <property name="serviceInterface">
            <value>com.edw.service.TestService</value>
        </property>
    </bean>
    
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/testService.service">testHttpInvoker</prop>
            </props>
        </property>
    </bean>

</beans>

and register your remoting-servlet.xml on your web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
			/WEB-INF/remoting-servlet.xml
        </param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>remoting</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>remoting</servlet-name>
        <url-pattern>*.service</url-pattern>
    </servlet-mapping>

    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

try to deploy it on your app-server. After that, try to execute your client side’s application. This is what happen on my server’s console

RemoteInvocationTraceInterceptor] DEBUG org.springframework.remoting.support.RemoteInvocationTraceInterceptor:73 - Incoming HttpInvokerServiceExporter remote call: com.edw.service.TestService.doSomething
[TestServiceImpl] DEBUG com.edw.service.TestServiceImpl:26 - im doing something
[RemoteInvocationTraceInterceptor] DEBUG org.springframework.remoting.support.RemoteInvocationTraceInterceptor:79 - Finished processing of HttpInvokerServiceExporter remote call: com.edw.service.TestService.doSomething
[DispatcherServlet] DEBUG org.springframework.web.servlet.DispatcherServlet:909 - Null ModelAndView returned to DispatcherServlet with name 'remoting': assuming HandlerAdapter completed request handling
[DispatcherServlet] DEBUG org.springframework.web.servlet.DispatcherServlet:591 - Successfully completed request

and this on my client’s console

[JdkDynamicAopProxy] DEBUG org.springframework.aop.framework.JdkDynamicAopProxy:113 - Creating JDK dynamic proxy: target source is EmptyTargetSource: no target class, static
[DefaultListableBeanFactory] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory:411 - Finished creating instance of bean 'testHttpInvoker'
[DefaultListableBeanFactory] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory:214 - Returning cached instance of singleton bean 'testHttpInvoker'
[SimpleHttpInvokerRequestExecutor] DEBUG org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor:133 - Sending HTTP invoker request for service at [http://localhost:8084/SpringHttpInvokerServer/testService.service], with size 21766
[Main] DEBUG com.edw.spring.main.Main:41 - 2.0E9

this is my project structure, btw ignore the jasypt.jar and commons-lang.jar on my project classpath, im not using them on this project.
my Netbeans 6.9 Client side's project structure

my Netbeans 6.9 Server side's project structure

If you are looking about a good Spring book, i would highly recommend “Professional Java Development with the Spring Framework”, Published by Wiley Publishing, Inc. FYI im using Spring 2.5.6

Have fun coding it, (H)

Yet Another Simple Swing, Spring and Ibatis Integration Example

I was working on my side project while drinking a cup of (C) when suddenly i had an idea, why cant i rely on Spring’s Transaction instead of Ibatis’ plain transaction. I see that Spring’s Transaction with annotation is much much simpler than Ibatis’ old fashioned transaction with try-catch and commit-rollback method. Okay, enough with the chit-chat. Let me show you the code.

First, i create a very simple database, with one table consist of 2 simple columns.

CREATE DATABASE 'test'
USE 'test'

CREATE TABLE 'contoh' (
  'nama' varchar(30) NOT NULL,
  'alamat' varchar(100) DEFAULT NULL,
  PRIMARY KEY ('nama')
) 

next step is creating a java bean for database mapping

package com.edw.bean;

public class Contoh {

    private String nama;
    private String alamat;

    public String getAlamat() {
        return alamat;
    }

    public void setAlamat(String alamat) {
        this.alamat = alamat;
    }

    public String getNama() {
        return nama;
    }

    public void setNama(String nama) {
        this.nama = nama;
    }
    
}

and an xml mapping for database queries, i named it contoh.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" 
"http://ibatis.apache.org/dtd/sql-map-2.dtd" >
<sqlMap namespace="contoh" >

  <resultMap id="result" class="com.edw.bean.Contoh">
        <result property="nama" column="NAMA" columnIndex="1"/>
        <result property="alamat" column="ALAMAT" columnIndex="2"/>
    </resultMap>

    <insert id="insertContoh" parameterClass="com.edw.bean.Contoh" >
    insert into contoh (nama, alamat)
    values (#nama:VARCHAR#, #alamat:VARCHAR#)
    </insert>

    <select id="selectAllContoh" resultMap="result">
    select nama, alamat
    from contoh
    </select>

</sqlMap>

and ibatis’ main xml configuration, sqlmapconfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

    <settings
          cacheModelsEnabled="true"
          enhancementEnabled="true"
          lazyLoadingEnabled="true"
          maxRequests="128"
          maxSessions="24"
          maxTransactions="12"
          defaultStatementTimeout="60"
          useStatementNamespaces="true"
       />

    <sqlMap resource="com/edw/sqlmap/contoh.xml"/>

</sqlMapConfig>

because im using Spring, i need one main xml configuration for my Spring app, i named it spring.xml

<?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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">


    <context:component-scan base-package="com.edw"/>
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <context:annotation-config/>

    <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="configLocation" value="com/edw/sqlmap/sqlmapconfig.xml"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost/test"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>
    </bean>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

</beans>

and 1 singleton class to load my configuration,

package com.edw.config;

/**
 *
 * @author edw
 */
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ApplicationContextProvider {

    private Logger logger = Logger.getLogger(ApplicationContextProvider.class);
    private ApplicationContext applicationContext;
    private static final ApplicationContextProvider provider = new ApplicationContextProvider();

    private ApplicationContextProvider() throws ExceptionInInitializerError {
        try {
            this.applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        } catch (Throwable ex) {
            logger.error("Initial ApplicationContext creation failed -- " + ex.getMessage(), ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public synchronized static ApplicationContextProvider getInstance() throws ExceptionInInitializerError {
        return provider;
    }

    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
}

i create a DAO class, to connect to my ibatis layer,

package com.edw.dao;

import com.edw.bean.Contoh;
import com.ibatis.sqlmap.client.SqlMapClient;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import org.springframework.stereotype.Repository;

/**
 *
 * @author edw
 */
@Repository(value = "contohDao")
public class ContohDao extends SqlMapClientDaoSupport {

    // empty constructor
    public ContohDao() {       
    }
     
    // autowired constructor
    // i dont know why, but i cant autowired sqlMapClient directly
    // it will cause  java.lang.IllegalArgumentException: Property 'sqlMapClient' is required
    @Autowired
    public ContohDao(SqlMapClient sqlMapClient) {
        setSqlMapClient(sqlMapClient);
    }

    public void insert(Contoh contoh){
        getSqlMapClientTemplate().insert("contoh.insertContoh",contoh);
    }

    public List<Contoh> select(){
        return getSqlMapClientTemplate().queryForList("contoh.selectAllContoh");
    }
}

and my Service class, i use it to connect to my DAO layer,

package com.edw.service;

import com.edw.bean.Contoh;
import com.edw.dao.ContohDao;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author edw
 */
@Service("contohService")
public class ContohService  {

    @Autowired
    private ContohDao contohDao;
    
    private Logger logger = Logger.getLogger(ContohService.class);

    @Transactional(isolation=Isolation.SERIALIZABLE)
    public void insert(Contoh contoh) {
        logger.debug("begin insert at "+this.getClass().getName());
        contohDao.insert(contoh);
        logger.debug("end insert at "+this.getClass().getName());
    }

    public List<Contoh> select() {
        logger.debug("begin select at "+this.getClass().getName());
        List<Contoh> contohs = contohDao.select();
        logger.debug("end select at "+this.getClass().getName());
        return contohs;
    }    
}

please be careful with isolation level, from what i’ve read,

In a typical application, multiple transactions run concurrently, often working
with the same data to get their job done. Concurrency, while necessary, can lead
to the following problems:

  • Dirty read—Dirty reads occur when one transaction reads data that has been
    written but not yet committed by another transaction. If the changes are
    later rolled back, the data obtained by the first transaction will be invalid.
  • Nonrepeatable read—Nonrepeatable reads happen when a transaction performs
    the same query two or more times and each time the data is different.
    This is usually due to another concurrent transaction updating the data
    between the queries.
  • Phantom reads—Phantom reads are similar to nonrepeatable reads. These
    occur when a transaction (T1) reads several rows, and then a concurrent
    transaction (T2) inserts rows. Upon subsequent queries, the first transaction
    (T1) finds additional rows that were not there before.

That’s why, im using Isolation.SERIALIZABLE, because

ISOLATION_SERIALIZABLE
This fully ACID-compliant isolation level ensures that dirty
reads, nonrepeatable reads, and phantom reads are all
prevented. This is the slowest of all isolation levels
because it is typically accomplished by doing full table
locks on the tables involved in the transaction.

this is my UI

package com.edw.ui;

import com.edw.bean.Contoh;
import com.edw.config.ApplicationContextProvider;
import com.edw.service.ContohService;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;

/**
 *
 * @author edw
 */
public class MenuUtama extends JFrame implements ActionListener {

    private JTextField txtNama = new JTextField();
    private JTextField txtAlamat = new JTextField();
    private JButton cmdButton = new JButton("Save");
    private Logger logger = Logger.getLogger(MenuUtama.class);

    public MenuUtama() {
        setLayout(new GridLayout(3, 3));
        Container con = this.getContentPane();
        con.add(new JLabel("nama : "));
        con.add(txtNama);
        con.add(new JLabel("Alamat : "));
        con.add(txtAlamat);
        con.add(cmdButton);

        cmdButton.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == cmdButton) {
            Contoh contoh = new Contoh();
            contoh.setNama(txtNama.getText());
            contoh.setAlamat(txtAlamat.getText());

            try {
                ApplicationContext ac = ApplicationContextProvider.getInstance().getApplicationContext();
                ContohService service = (ContohService) ac.getBean("contohService");
                service.insert(contoh);
                logger.debug("success");
            } catch (Exception ex) {
                logger.error(ex.getMessage(), ex);
            }
        }
    }

    public static void main(String[] args) {
        MenuUtama menuUtama = new MenuUtama();
        menuUtama.setVisible(true);
        menuUtama.setSize(300, 150);
        menuUtama.setLocationRelativeTo(null);
    }
}

this is my junit test case

package com.edw.test;

import com.edw.bean.Contoh;
import com.edw.config.ApplicationContextProvider;
import com.edw.service.ContohService;
import java.util.List;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.springframework.context.ApplicationContext;


/**
 *
 * @author edw
 */
public class TestKoneksi {

    @Test
    public void testingMain(){

        Logger logger = Logger.getLogger(TestKoneksi.class);

        ApplicationContext ac = ApplicationContextProvider.getInstance().getApplicationContext();
        ContohService service = (ContohService)ac.getBean("contohService");
        List<Contoh> contohs = service.select();

        for (Contoh contoh : contohs) {
            logger.debug(contoh.getNama()+" - "+contoh.getAlamat());
        }

        Contoh contoh = new Contoh();
        contoh.setNama("Ngorroc");
        contoh.setAlamat("Morroc");
        service.insert(contoh);

    }
}

this is the appereance of my swing app
ibatis swing spring app

this is what written on my console

[SqlMapClientTemplate] DEBUG org.springframework.orm.ibatis.SqlMapClientTemplate:177 - Opened SqlMapSession [com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl@b05acd] for iBATIS operation
[Connection] DEBUG java.sql.Connection:27 - {conn-100000} Connection
[SqlMapClientTemplate] DEBUG org.springframework.orm.ibatis.SqlMapClientTemplate:194 - Obtained JDBC Connection [com.mysql.jdbc.JDBC4Connection@17ec9f7] for iBATIS operation
[Connection] DEBUG java.sql.Connection:27 - {conn-100000} Preparing Statement:      insert into contoh (nama, alamat)     values (?, ?)     
[PreparedStatement] DEBUG java.sql.PreparedStatement:27 - {pstm-100001} Executing Statement:      insert into contoh (nama, alamat)     values (?, ?)     
[PreparedStatement] DEBUG java.sql.PreparedStatement:27 - {pstm-100001} Parameters: [ibatisInsert, testing masuk Ibatis]
[PreparedStatement] DEBUG java.sql.PreparedStatement:27 - {pstm-100001} Types: [java.lang.String, java.lang.String]
[ContohService] DEBUG com.edw.service.ContohService:28 - end insert at com.edw.service.ContohService
[DataSourceTransactionManager] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager:730 - Initiating transaction commit
[DataSourceTransactionManager] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager:259 - Committing JDBC transaction on Connection [com.mysql.jdbc.JDBC4Connection@17ec9f7]
[DataSourceUtils] DEBUG org.springframework.jdbc.datasource.DataSourceUtils:193 - Resetting isolation level of JDBC Connection [com.mysql.jdbc.JDBC4Connection@17ec9f7] to 4
[DataSourceTransactionManager] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager:314 - Releasing JDBC Connection [com.mysql.jdbc.JDBC4Connection@17ec9f7] after transaction
[DataSourceUtils] DEBUG org.springframework.jdbc.datasource.DataSourceUtils:312 - Returning JDBC Connection to DataSource
[MenuUtama] DEBUG com.edw.ui.MenuUtama:51 - success

my NB Project Structure and libraries that i used
Netbeans Project structure, libraries and stuffs

btw, i highly recommend these books to understand more about Spring and Ibatis framework.

  1. Manning Spring in Action 2nd Edition
  2. Manning Ibatis in Action

thank you, have fun and good luck.
:-[