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>

Wednesday, September 12, 2007

Chaining selects in iBatis

If you ever have to chain two selects because the Objects are related, there is some info about it on page 32 of iBatis user guide. I created a fully functional example to demonstrate how it is done. In the following example when we run Info, we will also have Address information for that person even though they are separate SqlMaps containing separate resultMaps

EXAMPLE
-------
Person.xml
---------
<sqlMap namespace="Person">

< id="infoMap" class="Details">
< property="PersonId" column="Id" javatype="java.lang.Long">
< property="PersonName" column="Name" javatype="java.lang.String">
< property="PersonAge" column="Age" javatype="java.lang.Long">
< property="PersonGender" column="Gender" javatype="java.lang.String">
< property="Address" column="Id" javatype="Address" select="Address.getAddressById">

< /resultMap>

< id="loadInfo" parameterclass="java.lang.Long" resultmap="infoMap">

SELECT Id, Name, Age, Gender
FROM Person
WHERE ssn = #value#

< /select>

1.Pass value of column specified in cloumn to select id 'getAddressById' in SqlMap with name space Address (contains address related queries)
javatype="Address" is a reslut bean for getAddressById containing fields Street, City, State and ZIP

Address.xml
-----------
<sqlMap namespace="Address">

< id="Address" class="Address">
< property="PersonStreet" column="Street" javatype="java.lang.String">
< property="PersonCity" column="City" javatype="java.lang.String">
< property="PersonState" column="State" javatype="java.lang.String">
< property="PersonZIP" column="ZIP" javatype="java.lang.Long">
< /resultMap>

< id="getAddressById" parameterclass="java.lang.Long" resultmap="Address">

SELECT Street, City, State, ZIP
FROM Address
WHERE id = #value#

< /select>

So, when you run infoMap above you will also have address details for that person.

Struts 2

I spent sometime this weekend researching Struts 2 and did a simple test project. It seems pretty cool. On Struts2 site, it says that it is a combination of Struts1.x + WebWork.

Comparing Struts 1 and 2
---------------------------------------------------------------
http://struts.apache.org/2.x/docs/comparing-struts-1-and-2.html

The good things that I liked
--------------------------------
1.No more dependency on HttpServletRequest and HttpServletResponse in Actions(My guess is it uses ThreadLocal in some fashion)
2. Actions are not singletons (don't have to worry about thread safety anymore)
3. Any POJO can be Action
3. No ActionForms
4. Spring aware Actions

It does seem like it is going simplify life by removing lot of redundancy and overhead but the down side seems like that it is not as matured as 1.x (http://raibledesigns.com/rd/entry/does_struts_2_suck)and doesn't have large community as 1.x. Hopefully as the time passes it gets better.

Tuesday, September 11, 2007

Extending DisplayTag to bring the user back to same page with same sorting Part-2

7. Copy the in quotes code and add it after this line in your MyDisplayTag

Integer pageNumberParameter = requestHelper .getIntParameter(encodeParameter(TableTagParameters.PARAMETER_PAGE));

this.pageNumber = (pageNumberParameter == null) ? 1

: pageNumberParameter.intValue();

“HttpServletRequest request = (HttpServletRequest) this.pageContext

.getRequest();

HttpSession session = request.getSession();

// get values from current request

Integer requestPageNum = new Integer(this.pageNumber);

int sortedColumn = -1; // list index starts with 0, so set it to -1

Integer sortColumnParameter = requestHelper

.getIntParameter(encodeParameter(TableTagParameters.PARAMETER_SORT));

sortedColumn = (sortColumnParameter == null) ? this.defaultSortedColumn

: sortColumnParameter.intValue();

if (sortColumnParameter == null) {

sortColumnParameter = new Integer(sortedColumn);

}

// String requestSortedColumn = "" + sortedColumn; //column index of

// sorted column

SortOrderEnum paramOrder = SortOrderEnum

.fromCode(requestHelper

.getIntParameter(encodeParameter(TableTagParameters.PARAMETER_ORDER)));

Boolean requestOrder = new Boolean(

SortOrderEnum.DESCENDING != paramOrder); // sorting order ASC

// or DSC. true==asc

// and false==dsc

String myPageNumber = (String) session.getAttribute(this.uid

+ "pagenum");

String mySortColumn = (String) session.getAttribute(this.uid

+ "sortedColumn");

String mySortOrder = (String) session.getAttribute(this.uid

+ "sortedOrder");

if (myPageNumber == null) {

myPageNumber = requestPageNum.toString();

}

if (mySortColumn == null) {

mySortColumn = sortColumnParameter.toString();

}

if (mySortOrder == null) {

mySortOrder = requestOrder.toString();

}

String myDisplayTag_UseSessionValues = (String) session

.getAttribute("myDisplayTag_UseSessionValues");

session.removeAttribute("myDisplayTag_UseSessionValues");

if ("true".equals(myDisplayTag_UseSessionValues)) {

//

// This means we should use the values from Session

//

requestPageNum = new Integer(myPageNumber);

sortColumnParameter = new Integer(mySortColumn);

requestOrder = new Boolean(mySortOrder);

this.pageNumber = requestPageNum.intValue();

}

// put current request values into session for next time.

session.setAttribute(this.uid + "pagenum", requestPageNum.toString());

session.setAttribute(this.uid + "sortedColumn", sortColumnParameter

.toString());

session.setAttribute(this.uid + "sortedOrder", requestOrder.toString());

session.setAttribute("uniqueTableId", this.uid);”


And the last thing you need to do is put a flag in session in Action class’s method in when the user leaves MyDisplayTag.

This is not the best way of doing it if you have more time but it is quick fix.

Sunday, September 9, 2007

Log4j.xml file instead of properties file

If for some reason you prefer to configure log4j in xml instead of usual properties file, I found out that you can do it very easy.

1. Create log4j.xml and put it in your apps class path, usually under web-inf.

I created simple log4j.xml as follows

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<!-- *#***We can also have XML file in class path instead of-->
<!-- properties file or you can put it where ever you want-->
<!-- and write a servlet and map it in web.xml -->

<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="${TOMCAT_HOME}/logs/server.log" />
<param name="Append" value="true" />
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] %m%n" />
</layout>
</appender>

Thats it. You can also put it anywhere in your app by doing this as mentioned in log4j manual here http://logging.apache.org/log4j/1.2/manual.html under Example Configurations -> Initialization servlet

Tuesday, September 4, 2007

Extending DisplayTag to bring the user back to same page with same sorting Part-1

This summary is not available. Please click here to view the post.

Threadlocal in Struts

Recently, I ran into a situation where I had to access ActionMapping while customizing Displaytag (outside of Action class) without changing any method signature to pass mapping. You can also use following technique to access request, response, session etc in any layer of the application.

After doing some search on the net I found an old friend (ThreadLocal).
I created a new calls called ThreadUtil as follows.

import java.util.HashMap;
import java.util.Map;

public class ThreadUtil {
private static ThreadLocal threadData = new ThreadLocal() {
protected synchronized Object initialValue() {
return new HashMap();
}
};
public static Object get(String key) {
return ((Map)ThreadUtil .get()).get(key);
}
public static void set(String key, Object val) {
((Map)ThreadUtil .get()).put(key,val);
}
}

After I created above class, I put my mapping as follows

ThreadUtil.set("mapping", mapping);

And retrieve it whereever you need as follows

ActionMapping mapping = (ActionMapping) ThreadUtil.get("mapping");

Though it is nothing new, I found it be very useful in my situation.

Friday, August 31, 2007

Scalability and Oracle ‘IN’ operator

The following solution is specific if you are using iBatis. Though it is not very common to have more than 1000 elements in Oracle "IN" operator if the system and ORM mappings are designed correctly, we all know it is not a perfect world.
The default limitation of Oracle ‘IN’ clause is 1000 elements (‘1’,’2’,’-‘,’1000’) but wha happens if you have 1005 elements. There are 2 ways one is configuring Oracle if you happen to have right permissions and DBAs are nice to you. But if that is not the case you can fall back on 2nd option as shown below.

For example this is what you have in Ibatis XML
< select id="getProductGroup" resultmap="result" parameterclass="java.lang.String">
---1005 comma separated strings (elements)
select * from table where xxx in #value#
</select>


The above works fine as long as you have 1000 comma separated strings but if you have more than 1000, you can replace it with the following.

< select id=" getProductGroup " resultmap="result" parameterclass="java.util.List">
--List containing comma separated strings
select * from table where
(
(instr (#[]# , ','||xxx||',') > 0)
)

< /select>

Of course, you will have to write utility class to create the parameter List.

Wednesday, August 29, 2007

Passing params to Struts Mapping

We all come across situations where we have to pass params to Struts Action Mapping from Action class to create new ActionForward. As with most of my posts my intent is to learn and share.

Here is your Action Class

public class ResourceAction extends Action {


public ActionForward filter(ActionMapping mapping, ActionForm form, pServletRequest request,
HttpServletResponse response)

//other code here
//Original Forward

return mapping.findForward(ForwardConstants.SUCCESS);

//Create new Action Forward with additional params

ActionForward actionForward = mapping.findForward(ForwardConstants.SUCCESS);
ActionForward newActionForward = new ActionForward (actionForward);
newActionForward.setPath(actionForward.getPath()+ paramString); //create new Forward
return newActionForward;


}

}