Monday, March 29, 2010

New Website -seenuonjava.com

I have been thinking about getting a new website for a while. The main reason for that is to show things in action that I talk in my posts. So I looked around for Tomcat and JBoss hosting and after doing some cost comparisons finally I settled on http://www.dailyrazor.com/ for their price. If you are interested check my site seenuonjava.com and check out working application for Java Thread Concurrency to Web Services and Integration post at http://seenuonjava.com/app/ecommerce-1.0.0-SNAPSHOT/

Monday, March 22, 2010

Hibernate org.hibernate.NonUniqueObjectException

You probably got this exception because your are trying to insert or update in a loop with some changes like

for (Record record : recordList) {
record.setName(name[i]);

...
...
session.saveOrUpdate(record);
}

When you have a persisted object and you change a value on it, it becomes dirty and hibernate needs to flush these changes to your persistence layer. So that Hibernate can synchronize the underlying persistent store with persistable state held in memory.
Flush and clean session to fix it, like below.

 for (Record record : recordList) {
record.setName(name[i]);
...
...
session.saveOrUpdate(record);
session.flush();
session.clear();
}
Check out my site seenuonjava.com for more

Wednesday, March 17, 2010

Hibernate Distinct Rows

In Hibernate when we do left outer join, sometimes you may get us duplicate rows, as Hibernate entities that we are joining, are themselves joined with some other entities.

For example:

We are joining Class A and Class B but class A already has a join with Class C which may give us
duplicate rows. In cases like these Hibernate has DISTINCT_ROOT_ENTITY for rescue, like below.

 @Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public List<Group> getGroups (String id) {
logger.info("Id is " + id);
Session session = sessionFactory.getCurrentSession();
List<Group> groups = session.createCriteria(Group.class)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.add(Restrictions.eq("id", id
.list();
return groups;
}
Check out my site seenuonjava.com for more.

Tuesday, March 16, 2010

Ordered ActiveMQ in Action

I have been thinking about getting ActiveMQ in Action (MEAP)for few days. After reading the first chapter (free to download) I am very impressed. I bought it a couple of days ago and I got to say that it is a great book and highly recommend it.

Best Tomcat Web Hosting

I have been looking around for hosting companies that provide either Tomcat 6 or JBoss hosting. I found a few that provide JBoss hosting but are way too expensive for me.

The idea is to use the new site as my development playground, sand box for my experiments and tutorials etc. So far I have found the following companies that provide Tomcat.

http://www.visionwebhosting.net/
Looks great, especially at $4/month but it seems like their regular plan supports
Tomcat 5.5.27, where as I am looking for Tomcat 6.
http://www.webhostingjava.net/
These guys support
Tomcat 5.5.27 too and little expensive for me at $20 /month.
http://www.dailyrazor.com/
So far the best I found at $6.95/month.

I am leaning towards http://www.dailyrazor.com/ as price is very reasonable and the best thing is they provide developer hosting. Let me know if you know any other hosting companies that provide Tomcat or JBoss hosting.

Monday, March 15, 2010

Java Thread Concurrency to Web Services and Integration

This is the first post in a series of discussions that talk about real world requirements and possible technology solutions in Java. This discussion talks about java thread concurrency and leads to the next article, whose primary focus will be SOA. The main purpose of the series is to discuss the best architectural solutions and alternatives to common requirements.

One of the common requirements these days is getting data from partners, for example getting stock prices, trading prices, checking if an item is available, supply chain information etc. One of my clients is a huge ecommerce company that sells electronics and other consumer goods online. Besides selling items from its own stock it has partnered with other companies for specific items. The sample application presented here is modeled after real world application and shows basic implementation using java queue and executor with spring MVC.

Besides concurrency, our sample application implements producer-consumer problem with BlockingQueue and ExecutorService(A.K.A. threadpoolexecutor (from google adwords suggest)).

Use Case:
When a customer searches for an item, the application searches for matches in its inventory system and partners’ inventory systems. For example, if a customer wants to search cameras he types “camera” in the website’s search box and submits. Upon submit, our application searches for available cameras, in the inventory system combines the results with results it received from external partners for display.


Sequence Diagram:
The following abstract sequence diagram shows order of processes that take place.

When a search request for an item comes to SearchController (Spring MVC controller), it invokes RequestProcessor.

 List searchResult = RequestProcessor.processRequest("camera");





RequestProcessor is the main class of the application and it is composed of a thread pool and a queue. Once invoked from the controller as above, it performs the following processes.

1. Get necessary information about partners like names, urls, usernames, passwords etc, search string and submits to ExecutorService, so that it can search all the partners concurrently.

 public List<String> processRequest(String searchString) {


for (int i = 0; i < partners.size(); i++) {
submitToThreadPool(searchRequest);

}
}//end processRequest
private static void submitToThreadPool(SearchRequest request) {
// uses Executors factory methods.
threadPool.execute(new ResultProcessor(request));
}// submitToThreadPool
2. While external partners are being searched for the item, it searches internal inventory system.

3. After results are received from internal inventory system, get results from partners from queue that are put in by ResultProcessor.
 String result = resultsQueue.poll(5, TimeUnit.MILLISECONDS);


4. Combine results from internal inventory system with results from external partners for display.

ResultProcessor implements Runnable and gets the search results from the partners. Once the results are received from partners, it puts them on the Queue for RequestProcessor (refer to step 3 above).

 private void getSearchResultsFromPartners(SearchRequest request) {


//gets results from partners and puts them on the queue
Resultsqueue.offer(partner.getMatchedItems(request .getSearchString()));
}//end getSearchResultsFromPartners


ResultProcessor implements Runnable and runs in a separate thread for each external partner concurrently.

Besides ArrayBlockingQueue, java.util.concurrent package contains bounded and unbounded queues like ConcurrentLinkedQueue, DelayQueue, LinkedBlockingQueue, PriorityBlockingQueue and SynchronousQueue.

BlockingQueue are best suited for producer-consumer queues, as they supports operations that wait for space, so producer threads can place data and wait for queue to be not empty, so consumer threads can get the data. This decoupling of producer and consumer allows for variable rates of data production and consumptions. Take a look at java.util.concurrent package for more information.

Executor is the primary abstraction of task execution in java. Executor provides a way of decoupling task submission from how each task will be run, including details of thread use, scheduling, etc. Combined together Blocking queue and Executor is the perfect recipe to implement producer-consumer pattern like we did.

In our next post we will expand our example to include different ways of connecting to external partners including web services using Apache CXF.

Download code from here. If you like to deploy the application and see it in action, copy ecommerce-concurrent.war file from target directory to your server. If you wish to build it yourself go to ecommerce-concurrent directory from command line and run “mvn package” to build war file.

Thursday, March 11, 2010

Spring and DWR Integration Setp by Step

It’s been a couple of years since I used DWR last time. After spending sometime on configuration I got it working on my current project with the following configuration. Add the following xml file to your project along with other spring context files you have. You can download xml file from my site seenuonjava.com


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
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-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-2.0.xsd">

<dwr:controller id="dwrController" debug="true" />

<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="alwaysUseFullPath" value="true" />
<property name="order" value="3" />
<property name="mappings">
<props>
<prop key="/dwr/**/*">dwrController</prop>
</props>
</property>
</bean>

<!-- Java Class that DWR calls -->
<bean id="dwrContractNumCheck" class="com.seenu.test.dwr.ContractsNumCheckDwr">
<!--DWR generated JavaScript name for above java class-->
<dwr:remote javascript="dwrContractNumCheck">
<!--Method for DWR to be included in the above JavaScript-->
<dwr:include method="checkNumOfContracts" />
</dwr:remote>
</bean>

<!--
Call to the above method returns Contract object,
so define a converter for it
-->

<dwr:configuration>
<dwr:convert type="bean" class="com.seenu.test.entity.Contract" />
</dwr:configuration>

</beans>


In my next post I will talk about end to end example.

Wednesday, February 18, 2009

'Super' experientment

public abstract class Test{

public void test (){
System.out.println("test");
}
}

public abstract class Test1 extends Test{

public void test (){
super.test();
System.out.println("test1");
}
}


public class Test2 extends Test1{

public void test ()
{
super.test();
System.out.println("test2");

}

public static void main (String [] args){
Test2 test3 = new Test2 ();
test3.test ();

}

}

Output:
test
test1
test2

Monday, August 4, 2008

Java Concurrency In Practice - Book Review

Check my review in javalobby http://java.dzone.com/reviews/java-concurrency-in-practice

Since I started working on java concurrency, I have been looking for a good book on concurrency that is clear, practical and easy to read. 'Java Concurrency in Practice' by Brain Goetz with Doug Lea etc, is by far the best one that I have come across. As opposed to Doug Lea's famous book 'Concurrent Programming in Java: Design Principles and Pattern' which I personally found hard to read and dry in style, this book is extremely well-written and relatively easy to read.

This book is very well organized and divided into four sections, starting from fundamentals like thread safety, atomicity, race conditions, locking, liveliness and goes on to concurrent collections like ConcurrentHaskMap, CopyOnWriteArrayList, BlcokingQueues, ConcurtrentLinkedQueue and other collections.

The second and third sections cover structuring concurrent applications, liveliness, performance and testing which includes Executor framework, boundedbuffers, thread life cycles overheads, context switches, different types of thread pools, thread factories, policies among some very useful techniques for reducing lock contention, lock stripping, avoiding dead locks etc.

I find chapter twelve ‘Testing Concurrent Programs’ particularly interesting and very useful considering how tricky and hard to test concurrent programs in real life.

And the last section covers advanced topics such Explicit locks and advantages and disadvantages of using intrinsic locks vs. explicit locks and read-write locks, performance considerations of using various types of locks, building custom synchronizers, atomic variables and non-blocking synchronization java memory model and annotations.


Recently while working on an application that deals with online advertising similar to Google Adwords and Adsense, I found myself referring to sections two and three very frequently for implementing boundedbuffers with BlockingQueues, ExecutorService and ThreadPools. The code examples presented are very practical and easy to understand.

In the end, this book is a must read for java developers, particularly if you are working with multi-threading and java.concurrenct package.

Wednesday, June 4, 2008

AES Encryption

Recently I had to work on encrypting some data, after doing some research on AES, DES, RC4, I settled on AES. I thought it might be useful to others as well; please feel free to use it. Basically I read key (string) from a file and do the encryption.

import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;

/**
* This program generates a AES key, retrieves its raw bytes, and
* then reinstantiates a AES key from the key bytes.
* The reinstantiated key is used to initialize a AES cipher for
* encryption and decryption.
*/

public class Encoders {


public static String doAes (String EncodeSring) throws Exception {

//get key(string) from a file
StringBuilder key = TemplateHandler.getTemplate("aesKeyFile");
byte[] rawKey = stringToKey (key.toString());
SecretKeySpec secretKey = new SecretKeySpec(rawKey, "AES");
// Instantiate the cipher
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encrypted = cipher.doFinal(EncodeSring.getBytes());
return asHex(encrypted);
}



/**
* Turns array of bytes into string
*
* @param buf Array of bytes to convert to hex string
* @return Generated hex string
*/
public static String asHex (byte buf[]) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;

for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");

strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}

return strbuf.toString();
}



public static byte[] stringToKey (String password) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance ("MD5");
} catch (NoSuchAlgorithmException ex) {
return new byte[0];
}
byte[] passwordBytes = null;
try {
passwordBytes = password.getBytes ("ISO-8859-1");
} catch (UnsupportedEncodingException ex) {
passwordBytes = new byte[0];
}
return md.digest(passwordBytes);
}
}

Wednesday, May 21, 2008

How to arrange words in a String alphabetically?

Similar to my last post about different way of reversing a string in java, how do you arrange words in Alphabetical order? As with my last post there are many ways one can do it. This is one of those variations. I did it as follows when I had to it for broad matching.

public class ArrangeWordsAlphabetically {

/**

* @param StringToBeOrdered

* Splits keyword at white space and arranges them alphabetically

*/

public String orderAlphabetically(String StringToBeOrdered) {

String stbr = StringToBeOrdered.toLowerCase();

String orderedString = new String();

ArrayList pList = new ArrayList();

String [] tempStr =null;

tempStr = stbr.split("\\s+");

for (int i = 0 ; i <>length ; i++) {

pList.add(tempStr[i]);

}

// sort list

Collections.sort(pList);

// iterate through list

for (String str : pList)

orderedString +=str + " ";

System.out.println(orderedString);

return orderedString;

}

}

How do you reverse words in a String?

I haven’t posted anything in last couple of months as I have been busy with new project. I have been getting lot of requests about sample code for different posts, sorry if I haven’t replied back to you.

Thought I will share something I had to do, other day even though I got asked this question in interviews multiple times over the years.

As we all know there are many different ways of doing it with for loop, while loop, StringToeknizer or Split() etc. Since I have been doing lot of concurrency programming these days using threads, pools, blocking queues, stacks, lists etc, I thought I will try something different as follows.

public class ReverseWords {


public String ReverseStringWords(String StringToBeReversed) {


String reversedString = new String();

Stack stack = new Stack();

String [] tempStr =null;

tempStr = StringToBeReversed.split("\\s+");

for (int i = 0 ; i <>length ; i++) {

stack.push(tempStr[i]);

}

while(!stack.empty()) {

reversedString += (String) stack.pop() + " ";

}

return reversedString.toLowerCase();

}

}

Wednesday, January 9, 2008

Passed SCEA 1 (Sun Certified Enterprise Architect)

I have been planning to write SCEA 1 (Sun Certified Enterprise Architect) certification for last couple months, finally started preparing for it late November. I started with Design Patterns by Head First. Nice read, very entertaining, I highly recommend this book. Next, borrowed UML distilled from Local library. I like this book for the reason that it is very small and concise, gives you basics of UML. As expected EJB is major part of the certification, best place to read specifications is SUN’s website.

One more resource that helped me was Sun Certified Enterprise Architecture for J2EE Technology Study Guide (Sun Microsystems Press). This book contains UML, EJB, Pattern, Security etc all in one place.

I scheduled my exam on Monday 3.00pm so I get whole weekend before the exam to review important topics. There were 48 questions in the exam and I got 43 correct. One word of advise though, try to get as many answers correct as possible on the first pass itself even if takes few seconds more per question than you planned. Make sure you answer all the questions in the first pass. I was expecting to have more time at the end to review few questions I wasn’t sure of, but I ended up having only 2 minutes (2nd pass) to review 18 questions before time was up.

I used following resources.

1. Head First Design Patterns
2. UML Distilled
3. EJB specifications
4. Sun Certified Enterprise Architecture for J2EE Technology Study Guide (Sun Microsystems Press)
5. http://nicky.cust.ipeer.se/moelholmweb/pages/mocks/mocks_scea.xml
6. http://www.geocities.com/subra_73/SCEA_Practice_Questions.htm

Off to part 2…

Tuesday, November 6, 2007

Open-Closed principle

This is one of the fundamentally principles of OO design. It basically states “Software entities should be open for extension, but closed for modification.”


For example image you have a Soda machine that gives you 2 types of sodas Coke and Pepsi. Let’s implement it. At first it may look as below.

Imagine few months down the line you got tired of drinking only Coke and Pepsi and wants to add Sprite. You have to create a new method in SodaMachine class called getSoda () that takes Sprite as argument, which means we have to change SodaMachine class whenever you want to add new soda, so SodaMachine class is not closed for modifications.

Now, lets apply OCP, it will look as follows.

Now if you want to add a new drink you do not have to change SodaMachine class at all (see parameter type of getSoda()).


So all you have to do is create a new class called Sprite that implements SodaType interface. This tells us that SodaMachine is closed for modifications but you can still extend its functionality for any other type of sodas.


Monday, November 5, 2007

Resign Patterns

While looking around the web, I cam across this funny link. Many of us agree that patterns help us to design and understand systems better, but on the lighter side http://www.lsd.ic.unicamp.br/~oliva/fun/prog/resign-patterns

Monday, October 1, 2007

Creating xFire Client

If you saw my post on 16th of September on creating a web service, you must have realized how easy it is. You can find a lot of information on creating web services but it is hard to find good information on how to create a client to consume the services. In this post I will detail how to do that.

  1. Before we start modify EchoImpl.java in web service provider project to below

// START SNIPPET: echo

package org.codehaus.xfire.spring.example;

/**

* Provides a default implementation of the echo service interface.

*/

public class EchoImpl implements Echo

{

public String echo(String in)

{

String test = in + “: SOA test is successful”;

return test;

}

}

// END SNIPPET: echo
1. Download and install xFire plugin for Eclipse.
2. From client application (Service consumer application), Generate java classes with WSDL we generated from 16th post. You will get around 6 to 7 classes including endpoint interface class which is abstract interface for service provider's end point, generated stub class which is an implementation of generated endpoint interface and service class (looks like Echoclient.java)
3. Now all we to do is retrieve PortType from service and call the method.

In our case, it will be like

EchoClient service = new EchoClient();

EchoPortType ept = service.getEchoPortType();

String test = ept.bounce(“Hello World”);

Above test string should return “Hello World : Your SOA test is successful”

Wednesday, September 26, 2007

Regular Expressions

As developers, we all use regular expressions at one time or other. But the problem is we do not have to use them often enough to remember them until we have to use them next time. Recently I had to use regex in validation.xml after a long gap. This information is mostly from different blogs, Google and other resources. This blog entry is for me as a future reference when I have to use them again. You can use it if you find useful.


  1. * : zero or more times in any combinations

Ex : [0-8]*

Input: ‘5’, ‘’, ‘2234’

Above expression states that allowed digits are 0 to 8 and can occur any number of times.

  1. [^0-8] : negation, not even once

Above expression states those digits 0 to 8 cannot occur. So only 9 is valid.

  1. z : ‘z’ must occur only once.
  2. z+ : ‘z’ must occur once or more. The difference between z+ and z* is in later case ‘z’ can occur zero times but in former case it must occur at least once.
  3. z{2} : ‘z’ must occur exactly 2 times.
  4. z{2,4} : ‘z’ must occur at least 2 times but not more than 4 times.
  5. z {2, } : ‘z’ must occur at least times and any number of times.
8 . z? : ‘z’ is optional but if it is there it cannot occur more than one time.


Friday, September 21, 2007

Java Filters and Struts

As Java developers we all know that filters are very useful in development. If you look at Struts2 you may have noticed that it uses filters extensively. In fact unlike controller servlet (ActionServlet) in struts.1x Struts2 uses Servlet Filter.

Recently I had to use a filter in an application based on Struts1.x and Spring to restrict access to some jsps if user tries to access them directly by typing in Resourcepath/xxx.jsp. I would like to share how I did it, if you ever need to do that.
Lets assume you have bunch of jsps in a folder called "restrict" and you want to restrict access to those jsps if user tries to get them by typing in path and jspname.jsp in address bar in a browser. To do that

1. Add a filter declaration in your web.xml as follows
< filter>
< filter-name>restrictAccessFilter < /filter-name>
< filter-class>com.srini.test.web.filter.RestrictAccessFilter </filter-class>


2. Next add following to create mapping in web.xml
< filter-mapping>
< filter-name>restrictAccessFilter < /filter-name>
< url-pattern>/restrict/* < /url-pattern>
< /filter-mapping>



3. Final step is actually creating a filter

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

public class RestrictAccessFilter implements Filter {

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


public void init(FilterConfig filterConfig) throws ServletException {
log.info("RestrictAccessFilter .init(): " + filterConfig.getFilterName());
}

public void doFilter(ServletRequest req, ServletResponse res,
FilterChain filterChain) throws IOException, ServletException {
if (log.isDebugEnabled()) {
log.debug("RestrictAccessFilter .doFilter():");
}

if (req instanceof HttpServletRequest) {
HttpServletResponse response = (HttpServletResponse)res;
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}

filterChain.doFilter(req,res);

}

public void destroy() {
}
}

You can have various constants instead of SC_FORBIDDEN, take a look here http://java.sun.com/j2ee/sdk_1.2.1/techdocs/api/javax/servlet/http/HttpServletResponse.html

You are done. If someone tries to access /restrict/secret.jsp filter intercepts the request and sends HTTP 403.

Sunday, September 16, 2007

xFire (Web Services) + Spring + Struts

Over the last couple of days, I spent few hours doing xFire tutorial. After couple of frustrating hours, things finally started falling in place. For the most part, I just followed the tutorial but I got stuck at few places. Hopefully this post will save you few hours. First, the documentation on xFire site is very good as a starting point.


As you might already know, XfireExporter is implemented as a part of Spring MVC controller which requires the service go thru DispatcherServlet, if you are using with Spring and Struts combination, we can use one of xFire's servlet "org.codehaus.xfire.spring.XFireSpringServlet" (see below)

1. Go to http://xfire.codehaus.org/ and download and configure as indicated (notice the dependencies)

2. Go to web.xml and add following pieces


< context-param> (If you have this as a struts plug in you can delete it from struts-config.xml)
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml
classpath:org/codehaus/xfire/spring/xfire.xml </param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- XFire WebService support servlet. -->
<servlet>
<servlet-name>XFireServlet </servlet-name>
<servlet-class>
org.codehaus.xfire.spring.XFireSpringServlet
</servlet-class>
</servlet>

<!-- Xfire Servlet Mapping -->

<servlet-mapping>
<servlet-name>XFireServlet </servlet-name>
<url-pattern>/services/* </url-pattern>
</servlet-mapping>

That’s it, as far as set up is concerned.

3. I usually like to keep my different “applicationContext” files like “applicationContext-dao.xml, applicationContext-soa.xml etc in a separate package called “Config”. If you do the same thing create new xml file called “applicationContext-soa.xml “

4. And in your applcationContext.xml (usually under WEB-INF) add following line to import applicationContext-soa.xml


<import resource="classpath:/com/cma/config/applicationContext-soa.xml" />

4. Open “applicationContext-soa.xml” and paste following code.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

<import resource="classpath:org/codehaus/xfire/spring/xfire.xml"/>

<bean id="xfire.xmlbeansServiceFactory"
class="org.codehaus.xfire.xmlbeans.XmlBeansServiceFactory"
singleton="true">
vconstructor-arg index="0">
<ref bean="xfire.transportManager"/>
</constructor-arg>
</bean>

<bean id="echoService" class="com.cma.soa.impl.EchoImpl" />


<bean name="echo"
class="org.codehaus.xfire.spring.remoting.XFireExporter">
<property name="serviceFactory">
<ref bean="xfire.serviceFactory"/>
<property name="serviceBean">
<ref bean="echoService"/>
<property name="serviceClass">
<value>com.cma.soa.Echo
</property>
</bean>



</beans>
5. Go to http://xfire.codehaus.org/Spring+Remoting to get code for Echo.java and EchoImpl

That’s it, you are in business. Restart your server and go to http://localhost:8080/cma/services/Echo?wsdl and see.

Thursday, September 13, 2007

iBatis- Passing more than one column in nested selects

Take a look at my recent post "Chaining selects in iBatis" which explains how to chain selects for related objects. There is also a way of passing more than one column, all you have to do change this line

< property="Address" column="Id" javatype="Address" select="Address.getAddressById">
to
< property="Address" column="{id=Id, name=Name}" javatype="Address" select="Address.getAddressById">

and in your result map.

< select id="getAddressById" parameterclass="java.lang.Long" resultmap="Address">
SELECT Street, City, State, ZIP FROM Address WHERE id = #id# And name=#name#
lt /select>