javaee

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)

A Simple Java Client Server Application using EJB3 and Glassfish3

Well, in this tutorial i want to show you how to create a simple client server application using java. Actually java has dozens of different network protocols, from a simple socket, hessian, burlap, SpringHttpInvoker, SOAP, XML and so on. But in this example, i will try to create a very simple client server application with EJB 3, using Glassfish 3 as JavaEE Container. As usual, i use Netbeans 6.9 with its default Glassfish3 installation.

First, i create a new JavaEE, EJB Module project, named CompressedEJBServer, and create a simple Stateless Session Bean in it

package com.edw.facade;

import javax.ejb.Remote;

/**
 *
 * @author edw
 */
@Remote
public interface ConnectionFacadeRemote {
    String sayHello(String string);
    int sayAge(int age);  
}

and its implementation

package com.edw.facade;

import javax.ejb.Stateless;

/**
 *
 * @author edw
 */
@Stateless
public class ConnectionFacade implements ConnectionFacadeRemote {

    public String sayHello(String string) {
        System.out.println("im at " + this.getClass().getName() + " method sayHello()");
        return "hello " + string;
    }

    public int sayAge(int age) {
        System.out.println("im at " + this.getClass().getName() + " method sayAge()");
        return age * 2;
    }
}

and that’s my EJB3 Server side files. Simple isn’t it?

Next step is creating a Standard Java Application project, for my EJB3 client application. It consist only 1 java file, for testing connection to the server.

package com.edw.main;

import com.edw.facade.ConnectionFacadeRemote;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import org.apache.log4j.Logger;

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

    private Logger logger = Logger.getLogger(Main.class);

    private void connect() {
        try {
            Properties props = new Properties();
            props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.enterprise.naming.SerialInitContextFactory");
            props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
            
            // glassfish default port value will be 3700, 
            // but im using tcpviewer to redirect my 50005 port to 3700
            props.setProperty("org.omg.CORBA.ORBInitialPort", "50005");

            InitialContext ctx = new InitialContext(props);
            ConnectionFacadeRemote connectionFacadeRemote = (ConnectionFacadeRemote) ctx.lookup("com.edw.facade.ConnectionFacadeRemote");
            logger.debug(connectionFacadeRemote.sayHello("edwin "));
            logger.debug("my age is " + connectionFacadeRemote.sayAge(12) + " years");
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
    }

    public static void main(String[] args) {
        Main x = new Main();
        x.connect();
    }
}

include these jars to your client side’s application,

auto-depends.jar
common-util.jar
config.jar
config-api.jar
config-types.jar
connectors-internal-api.jar
container-common.jar
deployment-common.jar
dol.jar
ejb.security.jar
ejb-container.jar
glassfish-api.jar
glassfish-corba-asm.jar
glassfish-corba-codegen.jar
glassfish-corba-csiv2-idl.jar
glassfish-corba-newtimer.jar
glassfish-corba-omgapi.jar
glassfish-corba-orb.jar
glassfish-corba-orbgeneric.jar
glassfish-naming.jar
gmbal.jar
hk2-core.jar
internal-api.jar
javax.ejb.jar
javax.jms.jar
javax.resource.jar
javax.servlet.jar
javax.transaction.jar
jta.jar
kernel.jar
management-api.jar
orb-connector.jar
orb-iiop.jar
security.jar
tiger-types-osgi.jar
transaction-internal-api.jar 

and dont forget to add CompressedEJBServer project into CompressEJBClient’s project

this is what happen if i run my client side’s application

[Main] DEBUG com.edw.main.Main:30 - hello edwin 
[Main] DEBUG com.edw.main.Main:31 - my age is 24 years

this is my Server side’s project structures

and this is my Client side’s project structures
My Client Side's Project Structure

and this is my TCP Viewer logs, i try to redirect my localhost’s port 50005 into my localhost’s port 3700 (Glassfish’s port), so i can see what is passing through my 50005 port via TCP Viewer’s console.

Hope this can help, have fun and good luck. May the Source be with You.
(*)