Wednesday, 13 July 2011

ResultSetExtractor in Spring


Create the entry in the database:
For this we will take flight database and flight entity as our pojo class.
See - Create flights in database and corresponding pojo class

Now using the ResultSetExtractor
First we will implement result set extractor
public class FlightResultSetExtractor implements ResultSetExtractor<List<Flight>> {

@Override
public Object extractData(ResultSet rs) throws SQLException {
List<Flight> flightList = new ArrayList<Flight>();
while(rs.next){
Flight flight = new Flight();
flight.setFlightNo(rs.getString(1));
flight.setCarrierName(rs.getString(2));
flightList.add(flight);
}
return list;
}
}

Now using the ResultSetExtractor
Initialize JdbcTemplate as jdbcTemplate first
public List<Flight> getAllTodaysFlight(){
String sql = "Get all flights where date=?";
Date today = getTodaysDate();
Object[] args = {date};
FlightResultSetExtractor extractor = new FlightResultSetExtractor();
return jdbcTemplate.query(src, args, extractor);
}

Wednesday, 6 July 2011

Eclipse : Creating and Sharing Launch Configurations

This happened again. I downloaded a Java product from sourceforge. It came with a .project, so it is easy enough to import it into the eclipse workspace. Now, comes the humdinger of the problem. How in the world should I launch the application. I can also see a tests package, how can I launch the tests?
Fortunately, eclipse solves this problem through launch configurations. If you are developing on eclipse there is no reason for not sharing the launch configurations along with the code. A launch configuration is a way to inform a fellow developer how to invoke the application. It is like providing a helping hand in during the initial stages - till he/she grows up and find how to launch the application, tests or whatever by themselves.

Temporary launch configurations

If you rightclick on a test case or a main class and used 'Run as...', eclipse creates a launch configuration and invokes the application for you. While developing an application (if you are like me) - you will accumulate a lot of launch configurations. These launch configurations are saved along with the workspace and not shared.

Creating a launch configuration

For creating a launch configuration start with a temporary launch configuration. Open the Run -> Run dialog... option from the eclipse menu, i.e. right click on the file Run As-> Run configuration:
Now select the run or launch script you want (by noting the program name )

  Change the launch configuration name. Use a name that includes atleast the project name and the type of launch it is. No one can understand what 'Main' or 'AllTests' stand for. It is easy to understand 'SampleApp - Main' or 'SampleApp - AllTests'. Here is H2Test, which says we are testing whether program can connect to H2 database.

  You can set the arguments for the VM as well as application from the (surprise!) Arguments tab.

 As far as possible parameterize the arguments. Do not ever use hard coded file names or directory names in a launch configuration that is shared. Eclipse has predefined variables 'file_prompt', 'folder_prompt' and 'string_prompt' for this purpose. When a launch configuration with such parameters is launched, Eclipse prompt the user to either select a file/folder or enter a string.
If your launch is dependent on a particular Java version (suppose you need atleast JDK 1.5 to work) - use the JRE tab to select the JRE. It is advisable to select a particular 'Execution environment' rather than an installed JRE.
The rest of the tabs are self explanatory. If you added any environment variables, remember to parameterize them wherever needed. Launch the configuration using the 'Run' option in the dialog and check everything works fine.

Sharing a launch configuration

If you want to share a launch configuration, you do it through the 'Run dialog'. For opening the run dialog use Run -> Run dialog... option from the eclipse menu. The sharing option is in the 'Common' tab of the run dialog.

 Select the 'Shared file' option. Select the project to which this launch configuration belongs. I suggest the launch configurations to be saved at the root of the project directory. You can also add the launch configuration to the favorites menu (either to Run or Debug). Just click on 'Apply' and the launch configuration is saved. From now onwards, anyone who imports your project can launch the application by just clicking on the launch configuration file and selecting Run as -> <launch name>.

Also if you want you can direct console output to some log file on the file system, under this common tab:
Now you can choose any option like workspace, filesystem or variable. Save the log file location.

Launch configuration best practices

  • Provide launch configurations for all modes of launch. For example, if your application can be launched in UI and command line mode, provide two launch configurations one for each.
  • Do not proliferate the project with temporary launch configurations. I have a separate project where I save all of my temporary launch configurations. This will be checked into the SCM, but not shared along with the project.
  • Provide a launch configuration for running all the tests (if exists).
  • Do not add optional launch configurations into the favorites. My suggestion is to add only the application and all tests into the favorite menu.
  • Parameterize the launch configurations using eclipse variables - folder_prompt, file_prompt and string_prompt.
  • Select an appropriate JRE using the JRE tab and an execution environment.
Finally, launch configurations are for fellow developers and not for end users. Keep it in mind when you create a configuration. Too much of hand-holding might not be needed.

Tuesday, 5 July 2011

Cascading Persistence in Hibernate

We have said, a number of times, that when an object is made persistent, that the objects it refers to are also made persistent. This was an oversimplification. In the mapping files for the classes, there is an attribute, cascade that lets us control how much, or how little, of a reference graph gets automatically persisted, deleted or updated. The values that it can be set to, and their meanings, are as follows:
  • none: no automatic action on the referenced object takes place.
  • save-update: automatically save or update the referenced object when the referencing object is saved or the transaction commits.
    delete: automatically delete the referenced object when delete() is called on the referencing object. Note that, if the referencing object is not deleted but merely removes its reference to the referenced object, then this option will not do anything and, potentially, a garbage (or orphan) object will be left in the database.
  • delete-orphan: automatically delete any object for whom the reference has been removed from the referencing object.
  • all: take the same actions as save-update and delete but not that of delete-orphan.
  • all-delete-orphan: take the same action as save-update, delete and delete-orphan.

Thursday, 30 June 2011

Books for CXF web service

Apache CXF web service Development

Do you use Apache CXF? If so, you might take an interest in "Apache CXF Web Service Development".

The book does a good job of covering CXF use cases, going beyond the usual trivial Jax-WS examples. It also covers Jax-RS (RESTful) web services, and covers each in enough detail that you're likely to find what you need when working with CXF.

Jax-WS has largely demystified basic web service development, so there's a great amount of content on the web that will show you how to quickly annotate a POJO to get a web service up and running. But what if you need to do contract-first (top down) development? Lightweight resources often conveniently bypass this more difficult trail, but this book does a good job of handling it. (This is no great accomplishment for a book on web service development, but it does set the tone for the types of things this book will show.)

It also covers restful web services. I'd say a Java developer either currently using or wanting to use Apache CXF. The book isn't a complete reference for CXF, but it does introduce all the important topics. Once introduced, there's enough content to either solve your problem or at least educate you enough to effectively research what remains.

This book can be found here.

Creating a web service using apache Axis 2

http://blog.sencide.com/2011/06/create-web-service-using-apache-axis2.html
http://www.ibm.com/developerworks/webservices/library/ws-devaxis2part1/index.html?ca=drs-

Wednesday, 29 June 2011

Writing method interceptors using Spring AOP

Spring is a great Java technology that has become a very popular application framework during the past few years. My intention is not to go through the whole concepts and architectural details of the framework, because that kind of information can be easily looked up starting at http://www.springframework.org. As the article title indicates, I intend to provide hands-on examples showing the minimal requirements to bundle certain Spring functionalities in your Java applications. So, because I will not go into the “what’s under the hood” approach unless absolutely necessary, most of the examples might require the knowledge of basic Spring concepts. Anyway, the basic idea is that you must RTFM before deciding if Spring is right for your application.
The first example is a short look at a simple method intercepting strategy. You can read all about this and the whole Spring AOP API here.The source code for this example can be found here. In the project directory run ant compile run to launch the application.
For the beginning let’s consider that we have the service MyService that that has a method doSomething() performing an operation which takes a long time to execute. Below you can see the (pretty dumb) code of this method.
public class MyService {
public void doSomething() {
for (int i = 1; i < 10000; i++) {
System.out.println("i=" + i);
}
}
}

In order to print out the performance statistics on the method call, we must first implement the interceptor that actually calculates the execution time for this method. To do this we need to implement the org.aopalliance.intercept.MethodInterceptor interface shipped with Spring. This is actually a callback providing access to the actual call of the methods of our service. The JavaDoc for this interface is here.

public class ServiceMethodInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = methodInvocation.proceed();
long duration = System.currentTimeMillis() - startTime;
Method method = methodInvocation.getMethod();
String methodName = method.getDeclaringClass().getName()  
                                   + "." + method.getName();
System.out.println("Method '" + methodName  
                         + "' took " + duration + " milliseconds to run");
return null;
}
}

Next we need to proxy our service in order to obtain an instance whose methods are being intercepted by our ServiceMethodInterceptor. To achieve this, all it takes is a little magic in Spring’s bean configuration file, as you can see below.

<beans>
<bean id="myService" class="com.test.MyService">
</bean>

<bean id="interceptor" class="com.test.ServiceMethodInterceptor">
</bean>

<bean id="interceptedService" class="org.springframework
                      .aop.framework.ProxyFactoryBean">
<property name="target">
<ref bean="myService"/>
</property>
<property name="interceptorNames">
<list>
<value>interceptor</value>
</list>
</property>
</bean>
</beans>

The key in this XML snippet is Spring’s built-in class org.springframework.aop.framework.ProxyFactoryBean which provides the actual proxying of our service. In order to obtain the desired effect we must set the target and interceptorNames properties for this bean. The target property represents the name of the bean that we want to proxy, which in our case is the myService bean. The interceptorNames property holds a list of bean names that will be used as interceptors for the proxied bean. So, yes, you can define more than one interceptor for your bean.
As everything seems to be packed pretty nice, all we need to do now is to have our service instantiated using Spring and call itâs doSomething method.

public class Test {
public static void main(String[] args) {
ApplicationContext ctx =  
           new ClassPathXmlApplicationContext("com/test/applicationContext.xml");
MyService myService = (MyService)ctx.getBean("interceptedService");
myService.doSomething();
}
}

So we need to look up the interceptedService bean in order to get the proxied service, but if we choose to remove the performance monitor we can simply lookup the initial myService bean.
Normally, after the method doSomething has run, you should see, as the last output line, something like this:
Method 'com.test.MyService.doSomething' took 281 milliseconds to run

Except from the MethodInterceptor Spring also offers other method interception strategies. For example you can choose to handle a method execution right before or immediately after the actual call, or when an exception is thrown during the execution of your method. The reference documentation about these types of interceptors that Spring offers is available here.

Please note that basic performance monitoring can also be achieved by using Spring’s built-in PerformanceMonitorInterceptor. We used this logic just as a sample for method intercepting, but as your intuition might tell you, this is just one of the many things you can do with this feature of Spring. For example, if you need to implement a fine-grained security module, you might choose not to allow the method call to execute if the user does not have rights on the business method. So, basically, you will have to see for yourself how you can use this functionality in your application.
I hope you find this article useful.

Programmatically opening an editor

Eclipse uses file associations for opening appropriate editor on a file. You can see this in action when you click on a Java file or a ant build file. The correct editor is opened for you. If you want to do the same thing in your own plugins - it could not be easier in 3.4.

The class org.eclipse.ui.IDE has a set of static functions that opens an editor and returns a handle to that editor. This function needs a IWorkbenchPage. We can typically get it by PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(). The second parameter is a handle to the file. It can be a reference to IFile, URI, IMarker, IEditorInput, IFileStore or a URI. The last two cases typically open editors for the files that are outside the file system.

I came across this gem when I need to open an editor on a OS file path. The file is in the workspace, but the path is OS specific. In this case I used ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(Path.fromOSString(file)) to convert the OS path into an IFile. The getFileForLocation() returns null in case the path does not belong to the workspace. That is OK - that is what I exactly wanted.

So here is the entire code:

String filePath = "..." ;
final IFile inputFile = ResourcesPlugin.getWorkspace()
.getRoot().getFileForLocation(Path.fromOSString(filePath));
if (inputFile != null) {
IWorkbenchPage page = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage();
IEditorPart openEditor = IDE.openEditor(page, inputFile);
}


If you want to position the cursor to a specific line in the editor - do the following.

int Line = ...
if (openEditor instanceof ITextEditor) {
ITextEditor textEditor = (ITextEditor) openEditor ;
IDocument document= textEditor.getDocumentProvider().
getDocument(textEditor.getEditorInput());
textEditor.selectAndReveal(document.getLineOffset(line - 1),
document.getLineLength(line-1);
}

Saturday, 25 June 2011

Setting Tomcat Heap Size (JVM Heap) in Eclipse

Recently while running Tomcat under Eclipse for one of the web application I was getting Java Heap memory related error java.lang.OutOfMemoryError.
What needs to be done here basically is to increase the jvm heap size. So for increasing the JVM Heap Size of Tomcat in Eclipse we have to set few VM arguments of the tomcat.
Follow the simple steps to change the Heap Size of Tomcat under Eclipse.
1. Open the Server tab in Eclipse and double click the Tomcat server to open Server Configuration.
Double click on the Apache Tomcat under server.
2. In Server Configuration, click on the Launch Configuration link under General Information.

3. Under Arguments tab, add following values in VM arguments.
As you can see just add the VM arguments:

To know more about -Xm options read this article.

FindBugs plugin for Eclipse

Some time ago I wrote a post about FindBugs – a powerful tool for static code analysis in Java. Today I want to tell you about an Eclipse plugin that allows you to integrate FindBugs into your favorite IDE and automatically use it on your code.

The plugin works only with Eclipse 3.3+. The install instructions are quite simple, although depending on your Eclipse version some details like button names may vary. Do not worry though – the installation shouldn’t take you more than 5 minutes (yes, I did check it ). Just go to Help -> Eclipse Market place and search it and then install it, like here:


After you have it installed you can configure its settings for every project you have in your workspace. You can choose what kind of bugs you want FindBugs to look for, how are they reported and when is FindBugs run. The nice thing is that you really do not have to do that as the default settings are pretty reasonable. To get to the settings menu you have to right click on the project and then choose Properties > FindBugs. It looks like this:

After all is configured it is time to run the FindBugs. If you have not set it to run automatically you can start it by right clicking on your project and choosing FindBugs > FindBugs. Below is an example of a code that has been analyzed by FindBugs. Can you see what is wrong with it?
package com.vaani.test;

public class TestClass {

int number;
String name;

@Override
public boolean equals(Object o){
return ((TestClass)o).name==this.name;
}
}
So let's just right click on the project and click FindBugs:
OR Go to Project properties and click find bugs and what we get is this:


Notice the little bug markers on the left side of the code – they point to the places where errors have been found. If you move your cursor over them you will get a list of all issues detected – exactly like with regular Eclipse Java warnings. All those errors can also be seen in a ‘Bug Explorer’ window with additional description. To see this window go to Window > Show View > Other > FindBugs > Bug Explorer OR you may also get this window directly. For our code sample the list of errors is as following:




As you can see FindBugs found 7 problems with the code. Have you managed to find them all by yourself? Even if you did you probably see that it is much easier and safer to have FindBugs to detect those for you. And now with this plugin it is also much easier!

Find Bugs with FindBugs

FindBugs is a tool for a static analysis of Java code. It basically goes trough your programs (both .class and .java files) and searches for patterns of most common bugs. When you run it against your code you see a GUI with a listing of all found errors which you can browse trough according to a category or a severity.

The list of bugs that FindBugs can find is almost endless: starting from synchronization issues (eg: bug in access to a shared variable), performance (inefficient operations), ending on dead code and unclosed files. If your project has more than a 1000 lines I bet you’ll find something!

Two things have to be said frankly: not all bugs found will be severe enough that it would be wise to fix them – sometimes the code is too old or crappy to risk the change (well, whose fault is that?). Secondly, not all bugs can be found trough static analysis so an empty FireBugs report does not mean everything is fine. There are many complementary ways to improve the quality of the code (like UnitTests, code reviews) and static analysis is only one of them.

To summarize: FindBugs can find a lot of embarrassing stuff in your code that you probably really want to find. Its not a miracle cure, but for sure you’ll benefit a lot from it. And what is probably most important: it’ really easy in use (download, unpack, run) and IT’S FREE! Just go to Help -> Eclipse market place and search it and install it. Enjoy

Friday, 24 June 2011

Naming threads created with the ExecutorService

When profiling applications it sometimes becomes a pain to understand where so many threads come from and what the hell they are doing.






If you’re like me and have a dependency on java.util.concurrent‘s API’s for anything concurrency-related, then you’ve certainly noticed that default thread names aren’t particularly helpful with the aforementioned problem.
Here’s a quick & dirty implementation of a ThreadFactory (based on Executors.DefaultThreadFactory) but with support for your own thread name prefixes.

public class NamedThreadFactory implements ThreadFactory {

// constants -----------------------------------------------------------------

private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);

// internal vars -------------------------------------------------------------

private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;

// constructors --------------------------------------------------------------

public NamedThreadFactory() {
this("ThreadPool(" + POOL_NUMBER.getAndIncrement() + "-thread-");
}

public NamedThreadFactory(String namePrefix) {
SecurityManager s = System.getSecurityManager();
this.group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
this.namePrefix = namePrefix + "(pool" +
POOL_NUMBER.getAndIncrement() + "-thread-";
}

// ThreadFactory -------------------------------------------------------------

public Thread newThread(Runnable r) {
Thread t = new Thread(this.group, r, this.namePrefix +
this.threadNumber.getAndIncrement() + ")", 0L);
if (t.isDaemon()) {
t.setDaemon(false);
}
if (t.getPriority() != Thread.NORM_PRIORITY) {
t.setPriority(Thread.NORM_PRIORITY);
}
return t;
}
}
Tip: If you’re using Spring, you can just use CustomizableThreadFactory and save yourself the trouble.

Wednesday, 22 June 2011

HttpClient (Apache commons) code sample

I was playing around with Apache commons Http utilities the last day. I used to use the java.net.* APIs to satisfy my HTTP(s) needs.
Here is a sample code which I wrote which takes a URL as input, sets the basic request parameters (e.g. cookie string) and set the proxy settings along with the user credentials.

import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;

public class HttpClientTest
{
public static void main(String[] args)
{
HttpClient client = null;
GetMethod getMethod = null;
int responseCode = -1;
byte[] responseStream = null;

String urlString = "http://www.facebook.com";
String cookieString = null;

try
{
// Creating the GetMethod instance
getMethod = new GetMethod(urlString);

// Retries to establish a successful connection the specified number
// of times if the initial attempts are not successful.
getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler(1, false));
getMethod.getParams().setParameter("http.socket.timeout", new Integer(5000));
getMethod.setRequestHeader(new Header("Cookie", "<COOKIE_STRING>"));

// Creating an HttpClient instance
client = new HttpClient();

// Proxy settings: Configures the proxy host, port & user
// credentials and the scope of the credentials.
client.getHostConfiguration().setProxy("<HOST>", <PORT>);
Credentials credentials = new UsernamePasswordCredentials
("<USERNAME>", "<PASSWORD>");
AuthScope scope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT);
client.getState().setProxyCredentials(scope, credentials);

// Sets the user-agent for the client instance
client.getParams().setParameter("http.useragent", "<USER_AGENT>");

// Sends the GET request and gets the response
responseCode = client.executeMethod(getMethod);
responseStream = getMethod.getResponseBody();

System.out.println("Response Code: " + responseCode);
System.out.println("Response Body: \n" + new String(responseStream));
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
getMethod.releaseConnection();
client = null;
}
}
}


Note: I was looking for an API set which does make use of its own Socket level implementation. I don’t think HttpClient got it’s own implementation as it claims to be 100% Java. If you know any API set which performs better than java.net.* APIs please feel free to share it.



Wink – A framework for RESTful web services from Apache

Apache Wink 1.0 is a complete Java based solution for implementing and consuming REST based Web Services. The goal of the Wink framework is to provide a reusable and extendable set of classes and interfaces that will serve as a foundation on which a developer can efficiently construct applications.
Taken from Apache Wink official site: Click Here
Wink consists of a Server module for developing REST services, and of a Client module for consuming REST services. It cleanly separates the low-level protocol aspects from the application aspects. Therefore, in order to implement and consume REST Web Services the developer only needs to focus on the application business logic and not on the low-level technical details.
REST Web Service design structure



The Wink Server module is a complete implementation of the JAX-RS v1.0 specification. On top of this implementation, the Wink Server module provides a set of additional features that were designed to facilitate the development of RESTful Web services.
The Wink Client module is a Java based framework that provides functionality for communicating with RESTful Web services. The framework is built on top of the JDK HttpURLConnection and adds essential features that facilitate the development of such client applications.

Tuesday, 21 June 2011

RMI using spring

Let us look at Spring’s support to Remoting.

Spring supports remoting for several different Remote Procedure Call models, including Remote Method Invocation (RMI), Caucho’s Hessian and Burlap, and Spring’s own HTTP invoker.

Spring offers a POJO-based programming model for both your server and client, no matter which remoting solution you choose. This is accomplished using a proxy factory bean that enables you to wire remote services into properties of your other beans as if they were local objects.

The client makes calls to the proxy as if the proxy were providing the service functionality. The proxy communicates with the remote service on behalf of the client. It handles the details of connecting and making remote calls to the remote service.

If the call to the remote service results in a java.rmi.RemoteException, the proxy handles that exception and rethrows it as an unchecked
org.springframework.remoting.RemoteAccessException. Remote exceptions usually signal problems such as network or configuration issues that can’t be gracefully recovered from. Since there’s usually very little that a client can do to gracefully recover from a remote exception, rethrowing a RemoteAccessException makes it optional for the client to handle the exception.

Spring simplifies the RMI model by providing a proxy factory bean that enables you to wire RMI services into your Spring application is if they were local JavaBeans. Spring also provides a remote exporter that makes short work of converting your Spring-managed beans into RMI services.

Spring’s RmiProxyFactoryBean is a factory bean that creates a proxy to an RMI service. RmiProxyFactoryBean produces a proxy object that talks to remote RMI services on behalf of the client. The client talks to the proxy through the service’s interface as if the remote service were just a local POJO.

RmiProxyFactoryBean certainly simplifies the use of RMI services in a Spring application. But that’s only half of an RMI conversation.

Spring provides an easier way to publish RMI services. Instead of writing RMI-specific classes with methods that throw RemoteException, you simply write a POJO that performs the functionality of your service. Spring handles the rest.

For a typical Spring Application we need the following files:

1. An interface that defines the functions.

2. An Implementation that contains properties, its setter and getter methods, functions etc.

3. A XML file called Spring configuration file.

4. Client program that uses the function

Because the service interface doesn’t extend java.rmi.Remote and none of its methods throw java.rmi.RemoteException, this trims the interface down a bit. But more importantly, a client accessing the service through this interface will not have to catch exceptions that they probably won’t be able to deal with. Instead of generating a server skeleton and client stub using rmic and manually adding it to the RMI registry (as you would in conventional RMI), we’ll use Spring’s RmiServiceExporter.

RmiServiceExporter exports any Spring-managed bean as an RMI service. RmiServiceExporter works by wrapping the bean in an adapter class. The adapter class is then bound to the RMI registry and proxies requests to the service class.

Example Code
The simplest way to use RmiServiceExporter to expose the employeeService bean as an RMI service is to configure it in Spring with the following XML:

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="serviceName" value="employee-service"/>
<property name="service" ref="employeeService"/>
<property name="serviceInterface" value="rmi.common.EmployeeI"/>
<property name="registryPort" value="1234"/>
</bean>

Here the employeeService bean is wired into the service property to indicate that RmiServiceExporter is going to export the bean as an RMI service. ServiceName property names the RMI service and the serviceInterface property specifies the interface implemented by the service.

<bean id="employeeService" class="rmi.server.EmployeeImpl">
</bean>

Now let us look at an example...

Let us have simple employee recruitment service exposed through EmployeeI interface which contains methods to add, remove and get number of employees.

public class Employee implements Serializable {
private String name;
private String address;

public Employee(String name,String address){
this.name = name;
this.address = address;
}

// getters and setters
}


public interface EmployeeI {

public void addEmployee(Employee employee);

public void removeEmployee(Employee employee);

public List<Employee> getEmployees();

}

Here is the implementation for EmployeeI interface.

public class EmployeeImpl implements EmployeeI{

private List<Employee> employees = new ArrayList<Employee>();

public void addEmployee(Employee employee) {
employees.add(employee);
}

public void removeEmployee(Employee employee){
employees.remove(employee);
}

public List<Employee> getEmployees() {
return employees;
}
}

On the server side, we need to configure Spring to export the service through RMI. As we discussed earlier we can do it by RmiServiceExporter.
The interface can be accessed by using RmiProxyFactoryBean, or via plain RMI in case of a traditional RMI service. The RmiServiceExporter explicitly supports the exposing of any non-RMI services via RMI invokers. Of course, we first have to set up our service in the Spring container:

<beans>
<bean id="employeeService" class="rmi.server.EmployeeImpl"/>

<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="serviceName" value="employee-service"/>
<property name="service" ref="employeeService"/>
<property name="serviceInterface" value="rmi.common.EmployeeI"/>
<property name="registryPort" value="1234"/>
</bean>
</beans>

Now to run the server side service you need Spring context initialization.
public class EmpServerDemo {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext 
                  ("rmi/server/rmi-server-context.xml");
}
}


Now let us have a look at client side.

To link in the service on the client, we'll create a separate Spring container, containing the simple object and the service linking configuration bits:

<beans>
<bean id="employeeService"  
             class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="rmi://localhost:1234/employee-service"/>
<property name="serviceInterface" value="rmi.common.EmployeeI"/>
</bean>
</beans>

You can make client calls through the below code...

public class EmpClientDemo {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext 
                       ("rmi/client/rmi-client-context.xml");
EmployeeI employee = (EmployeeI) ctx.getBean("employeeService");
employee.addEmployee(new Employee("Prashant", "address1"));
employee.addEmployee(new Employee("Sneha", "address2"));
List<Employee> employees = employee.getEmployees();
System.out.println("Total number of employees: " + employees.size());
Iterator<Employee> it = employees.iterator();
while (it.hasNext()) {
Employee emp = (Employee) it.next();
System.out.println(" " + emp);
}
}
}

Therefore, the client will not be aware of the fact that the service is running remote and even less about the fact that its method calls are marshaled through RMI. The Spring bean configuration file takes care of these details, so the client code will not be affected if we change the remoting strategy or even if we choose to run the service in-process.

First run the EmpServerDemo in one console to launch the RMI server and then run the EmpClientDemo in another console.