Tuesday, December 15, 2009

How to configure Global/Default Interceptor in Struts 2

Global/Default interceptor means to me like the interceptor would be applied to the entire action classes may span accross mutiple packages.

Step 1: Create an interceptor
Step 2: Register the interceptor in interceptors tag.
Step 3: Create an interceptor stack having all the necessary references to the interceptors
Step 4: If there are multiple packages are involved then put the interceptor in the common package and
all other packages would extend it.

For Example:

<struts>
<package name="base-package" extends="struts-default">

<interceptors>
<!-- interceptor used to initialize resource used through out the application-->
<interceptor name="ResourceInit" class="com.test.ResourceInitInterceptor"/>

<!-- interceptor stack composes struts provided interceptors and custody related-->
<interceptor-stack name="base-default-stack">
<interceptor-ref name="ResourceInit"/>
<!-- "defaultStack" defined in struts in struts-default.xml-->
<interceptor-ref name="defaultStack"/>
</interceptor-stack>

</interceptors>

<!-- Default interceptor executed for the entire actions -->
<default-interceptor-ref name="base-default-stack"/>
</package>

<include file="/com/struts_config/struts_module_1.xml" />
<include file="/com/struts_config/struts_module_2.xml" />

</struts>

Note: struts_module_1 and struts_module_2 must extends "base-package"

Sunday, December 13, 2009

XA-DataSource and Non-XA Datasource in Global Transaction

Datasource - XA datasource is a data source that can participate in an XA global transaction.

Non-XA Datasource - Non-XA datasource generally can't participate in a global transaction.

An XA transaction, in the most general terms, is a "global transaction" that may span multiple resources. A non-XA transaction always involves just one resource.

An XA transaction involves a coordinating transaction manager, with one or more databases (or other resources, like JMS) all involved in a single global transaction. Non-XA transactions have no transaction coordinator, and a single resource is doing all its transaction work itself (this is sometimes called local transactions).

When the implementation code surrounded/enclosed by the global (XA) transaction then the entire code must be treated as unit irrespective of number of datasource(s) are involved in the unit. Therefore when you say "commit", the results are committed across all of the resources and when you say "rollback", _everything_ is rolled back across all resources (XA-Enabled Datasource).

If there are non-xa enabled datasource surrounded by global transaction (XA transaction) then it does not participate in the transaction therefore operation associated to the non-xa datasource has to be committed or rollback manually. As
J2EE Specification says that transaction can not be nested here there must not be opened separate transaction for non-xa datasource inside the global transaction. Non-XA datasource is a local datasource which can be commit/rollback without using any transaction boundary for it.

How to configure Global Transaction using Spring AOP:

Add the following configuration in the applicationContext.xml file:

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

<bean id="txManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="javax.transaction.TransactionManager" />
</bean>


<!-- the transactional advice -->
<tx:advice id="defaultTxAdvice" transaction-manager="txManager">
<!--the transactional semantics...-->
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true" />
<!-- other methods use the default transaction settings -->
<tx:method name="*" rollback-for="List Checked Business Exception separated by comma" />
</tx:attributes>
</tx:advice>

<aop:config>
<aop:pointcut id="com.test.operations"
expression="execution(* com.test.service.ServiceImpl.*(..))" />
<aop:advisor advice-ref="defaultTxAdvice" pointcut-ref="com.test.operations" />
</aop:config>

</beans>

Note: If applicaton server Transaction manager specific selected then just change JtaTransactionManager to their respective classes for example for weblogic it's "org.springframework.transaction.jta.WeblogicJtaTransactionManager"

Special configuration for JTA having more that 30 Seconds timeout:
i. Set Timeout to 180 seconds (if plans ) during DataSource Configuration
ii. Goto JTA > Set 180 seconds timeout and restart the app server to be effective.

Friday, September 25, 2009

Notes About Inner Class - Core Java

1. Innerclass nested with other class i.e. enclosing class. They are four types:
i. Static
ii. Member class
iii. Local class
iv. Anonymous Class

N.B - Inner class is a member of enclosing class like method or field.

2. Static Member Class/Interface:
i. Static class is a static member of class like static method/field.
ii. Interfaces can be defined as static member class.
iii. A static member class is not associated with any instance of the containing class (i.e., there is no this object).
iv. A static member class has access to all static members of its containing class, including private members. The reverse is true as well: the methods of the containing class have access to all members of a static member class, including the private members. A static member class even has access to all the members of any other static member classes, including the private members of those classes.
v. A static member class cannot have the same name as any of its enclosing classes. In addition, static member classes and interfaces can be defined only within top-level classes and other static member classes and interfaces.

5. Member Class

i.Member class is a member (instance) of the enclosing class and has access to any and all methods or variables of enclosing one and even the parent's this reference.
ii. A member class cannot have the same name as any containing class or package.
iii. Member classes cannot contain any static fields, methods, or classes (with the exception of constant fields declared both static and final). The reason of it as static fields, methods, and classes are top-level constructs not associated with any particular object, while every member class is associated with an instance of its enclosing class. Defining a static top-level member within a non-top-level member
class simply promotes confusion and bad programming style, so you are required to define all static members within a top-level or static member class or interface.
iv. Interfaces cannot be defined as member classes. An interface cannot be instantiated, so there is no object to associate with an instance of the enclosing class. If you declare an interface as a member of a class, the interface is implicitly static, making it a static member class.
v. To access the this reference of the containing class use classname.this

6. Local classes are declared within a block of code and are visible only within that block, just as any other method variable.

7. An anonymous class is a local class that has no name.

8. Advantages of inner classes can be an object-oriented advantage, an organizational advantage, and a call-back advantage.

i. Lets prove the above three advantages:

Object-Oriented
---------------
Let's look at the member class. Since its instance is a member of its parent instance, it has access to every member and method in the parent. At first glance, this might not seem like much; we already have that sort of access from within a method in the parent class. However, the member class allows us to take logic out of the parent and objectify it.

Organizational
--------------

Inner classes allow us to further organize our package structure through the use of namespaces. Instead of dumping everything in a flat package, classes can be further nested within classes. Explicitly, without inner classes, we were limited to the following hierarchy structure

Callback
--------

Inner member classes and anonymous classes both provide a convenient method for defining callbacks. The most obvious example relates to GUI code.

As with anything else, you have to take the good with the bad. Inner classes have their disadvantages. From a maintenance point of view, inexperienced Java developers may find the inner class difficult to understand. The use of inner classes will also increase the total number of classes in your code. Moreover, from a development point of view, most Java tools come up a bit short on their support of inner classes.

Ref: http://docstore.mik.ua/orelly/java-ent/jnut/ch03_10.htm

Notes about Inheritance - CoreJava

1. All the classes implecitly extends from Object class as it defines and implements common behaviour to the all classes.
2. You can declare a field in the subclass with the same name as the one in the superclass, thus hiding it (not recommended).
3. You can write a new instance method in the subclass that has the same signature as the one in the superclass, thus overriding it.
4. You can write a new static method in the subclass that has the same signature as the one in the superclass, thus hiding it.
5. You can write a subclass constructor that invokes the constructor of the superclass, either implicitly or by using the keyword super. Remember Constructors are not inheritable.
6. private member is accesible from the subclass indirectly. i.e. superclass is having public/protected method which access the private variables in generally its setter/getter method.
7. Remember a nested class has access to private members i.e. field/method of its enclosing class. Seems to be violated the encapsulation principles. Therefore, a public or protected nested class inherited by a subclass has indirect access to all of the private members of the superclass.
8. Do the casting after checking with instanceof operator.

9. Method overriding (hiding)

The overriding method has the same name, number and type of parameters, and return type as the method it overrides. An overriding method can also return a subtype of the type returned by the overridden method. This is called a covariant return type. Remember the access specifier has to be same or widen/higher scope not lesser if so compile time error.

It is recommended that use @override, as it instructs the compiler that you intend to override a method in the superclass. If, for some reason, the compiler detects that the method does not exist in one of the superclasses, it will generate an error.

Another point to remember that the distinction between hiding (static) and overriding (instance) has important implications. The version of the overridden method that gets invoked is the one in the subclass. The version of the hidden method that gets invoked depends on whether it is invoked from the superclass or the subclass.

************************Summary*********************************
------------------------| Super Instance Method -----| Super Static Method
------------------------|-----------------------------|-----------------------------
Sub Instance Method ----| Overrides ------------------| compile-time error
------------------------|-----------------------------|-----------------------------
Subclass Static Method -| compile-time error ---------| Hides


Remember Static method calls on type whereas instance method calls on instance.

10. Java does not support (i.e. intensinally eliminated to make simple) multiple inheritance implementation (i.e. class). There is a well known problem in multiple inheritance i.e. diamond problem. like consider the following example

Animal class is having method called talk().

Two classes i.e. Frog and Dinosaur each extends (error in java) Animal and implements talk().

Another class Frogosaur extends both Dinosaur and Frog and trying to call talk on type Animal. Here is the problem like ambiguity arises.

11. Interfaces give you more polymorphism than singly inherited families of classes, because with interfaces you don't have to make everything fit into one family of classes

12. Advantage of composition over inheritance (composition is quite better one to go with if it fits for the requirement)

i. It's easier to change classes involved in a composition relationship than it is to change classes involved in an inheritance relationship
ii. Composition allows you to delay the creation of back-end objects until (and unless) they're needed. It also allows you to change the back-end objects dynamically throughout the lifetime of the front-end object. With inheritance, you get the image of the superclass in your subclass object image as soon as the subclass is created, and it remains part of the subclass object throughout the lifetime of the subclass.
iii. It's easier to add new subclasses (inheritance) than it is to add new front-end classes (composition), because inheritance comes with polymorphism. If you have a bit of code that relies only on a superclass interface, that code can work with a new subclass without change. This isn't true of composition, unless you use composition with interfaces.

13. Remember that inheritance refers to "is-a" relationship (permanent) therefore easy to understand. Whereas Composition refers to "has-a" relationship and gives more flexibility.

14. Interface provides great extend for polymerphism

Wednesday, June 10, 2009

Java Performance Tunning - Compiled




Core Java:

1. StringBuilder is better than StringBuffer, though both are usually better than using string concatenation to build strings (when performing extensive String manipulation, replacing + with StringBuilder.append is likely recommended)

2. Declare method arguments final if they are not modified in the method. In general declare all variables final if they are not modified after being initialized or set to some value.

3. Declare methods private and/or final whenever that makes sense.

4. Use static final when creating constants

5. Use zero-length arrays instead of null

6. HashMap has slightly better performance than LinkedHashMap

7. HashSet has slightly better performance than LinkedHashSet

8. Replace strings and other objects with integer constants. Compare these integers by identity.

9. Use primitive data types instead of objects as instance variables.

10. Overwrite compareTo() method for object comparision rather comparing in the loop. ( Implementing compareTo/hashCode
http://www.javapractices.com/topic/TopicAction.do?Id=10
http://www.javapractices.com/topic/TopicAction.do?Id=28 )

11. Logging the contents of a Collection is simple (JDK 1.5 onwards)

Arrays.toString(myArray);
Arrays.deepToString(myObjectArray); //recursive
Arrays.asList(myArray).toString();

12. To determine if two String objects match exactly, you should almost always use the equals method, and not the == operator

13.Follow naming convention for distinguishing between local variables, arguments, and fields strictly. (Code review would be very productivity)

14. Good example on ArrayList vs Linked List

14.1 Appending elements to the end of a list has a fixed averaged cost for both ArrayList and LinkedList. For ArrayList, appending typically involves setting an internal array location to the element reference, but occasionally results in the array being reallocated. For LinkedList, the cost is uniform and involves allocating an internal Entry object.

14.2 Inserting or deleting elements in the middle of an ArrayList implies that the rest of the list must be moved. Inserting or deleting elements in the middle of a LinkedList has fixed cost.

14.3 A LinkedList does not support efficient random access

14.4 An ArrayList has space overhead in the form of reserve capacity at the end of the list. A LinkedList has significant space overhead per element.

14.5 Sometimes a Map structure is a better choice than a List.

Get some more good stuff in the following URL: http://java.sun.com/developer/JDCTechTips/2002/tt0910.html
http://www.pankaj-k.net/archives/2004/06/arraylist_versu.html http://www.informit.com/guides/content.aspx?g=java&seqNum=95
http://www.javapractices.com/topic/TopicAction.do?Id=65

Database:

1. Stay away from the database as much as possible.

2. Cache as much as feasible - an in-memory cache is better than an on-disk one, which in turn is better than a remote or a relational database.

3. Caching coarse-grained objects is better than caching fine-grained ones.


Project Health:

1. Load testing can provide the basis for: Comparing varying architectural approaches; Performance tuning; Capacity planning. (TBS)

2. Initially you should identify the probable performance and scalability based on the requirements. You should be asking about: numbers of users/components; component interactions; throughput and transaction rates; performance requirements. (TBS)

3.Performance measurements should be from presentation start to presentation completion, i.e. user clicks button (start) and information is displayed (completion). (TBS)

4. Select performance benchmarks and use them to quantify the scalability and determine performance targets and future performance improvements or degradations. Include all user types such as "information-gathering" visitors or "transaction" visitors in your benchmarks.

5. Technical Problem - Different Source For Tooling, Build Solution, RAD Solution, Framework Lib, Server and more important No One owns the whole productivity Experience if project is developed using many open source project / lib.

Java Web Tech:

1. Excessive use of custom tags may create unnecessary processing overhead.

2. Use the include directive where possible, as this is a compile-time directive as it is faster than the include action

3. Logging is more important than the performance saved by not logging.

4. There is little performance penalty to using an MVC architecture.

5. To ensure good performance use experienced J2EE builders and use proven design patterns.


Thursday, May 28, 2009

Pointer To Spring Stuff





Wednesday, May 27, 2009

How to fill VARRAY/TABLETYPE object in iBatis



Sample:

Step 1: Create DEMO_TABLE_TYPE as the following structure:
create or replace TYPE DEMO_TABLE_TYPE AS OBJECT
(
id NUMBER, name NVARCHAR2(35)
);

Step 2: Write demoProcedure as the following structure:
demoProcedure(
demoTType
) IS
BEGIN
INSERT INTO DEMOTABLE( ID, NAME) VALUES ( demoTType.ID,demoTType.NAME); END demoProcudre;

Step 3: create a sql map id in sql-map-xxx.xml like as follows:

<procedure id="demoProc" parameterClass="map">
<![CDATA[{call
DECLARE
demoTType DEMO_TABLE_TYPE := DEMO_TABLE_TYPE();
idx BINARY_INTEGER := 1;
BEGIN
]]>
<iterate property="list">
<![CDATA[
demoTType .extend(1);
demoTType (idxLF) := DEMO_TABLE_TYPE(
#demoTType[].id:NUMERIC#,
#demoTType[].name:VARCHAR#
);
idx := idx + 1;
]]>
</iterate>
<![CDATA[
demoProcedure(
demoTType
);
END}
]]>
</procedure>

Generic iBatis Error in Huge Volume Cetric Data

Error
com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred while applying a parameter map.
--- Check the BillIe.insertBillIssuingEntityOnEditCycle-InlineParameterMap.
--- Check the statement (update procedure failed).
--- Cause: java.sql.SQLException: ORA-06550: line 1, column 1:
PLS-00123: program too large (Diana nodes)

Solution:

Step 1: Create a store procedure which would insert/delete record from table

Step 2: Define some threshold value (Note: you must be ensure that threshold value won't encounter Diana nodes kind of problem) in java.

Step 3: Push records in batch mode

Pseudo Code Snippet


getSqlMapClient().startTransaction()
getSqlMapClient().startBatch()

//Check out how many records are there in the modelMap or List

totalRecord = modelList.size

toIndex = modelList.size

fromIndex =0

numberOfLoops = new Double(Math.ceil(totalRecord / THRESHOLD_VALUE)).intValue()

if(THRESHOLD_VALUE <= toIndex){
toIndex = new Double(THRESHOLD_VALUE).intValue()
}

for(int i = 0; i <>

modelSubList = modelList.subList(fromIndex , toIndex)

getSqlMapClient().insert("sql-map-id", modelSubList )

modelList.subList(fromIndex, toIndex).clear()

if(modelList.size() < THRESHOLD_VALUE){
toIndex = modelList.size();
}

}

getSqlMapClient().executeBatch()
getSqlMapClient().commitTransaction()

Quotation



  • FAIL FORWARD - FAILURE IS THE ONLY OPPORTUNITY TO BEGIN AGAIN MORE INTELLIGENTLY.



How to use Lucene Search in Struts 2.0

In Progress...

Monday, May 25, 2009

URLs About Servlet 3.0 Specification

1. Specification - http://jcp.org/en/jsr/detail?id=315
2. Good explanation in briefly - http://www.infoq.com/news/2007/06/servlet3
3. Good Presentation by Mark - http://people.apache.org/~markt/presentations/2009-04-01-Tomcat7Servlet3.pdf
4. http://today.java.net/pub/a/today/2008/10/14/introduction-to-servlet-3.html
5. http://blogs.sun.com/swchan/entry/servlet_3_0_annotations
6. http://blogs.sun.com/jluehe/
7. http://blogs.sun.com/swchan/
8. http://techtracer.com/2007/07/23/servlet-30-the-journey-begins-now/

Framework Stuff URL






Spring :
1. http://static.springframework.org/spring/docs/2.5.x/reference/orm.html
2. http://book.javanb.com/Professional-Java-Development-with-the-Spring-Framework/BBL0021.html
3. http://www.javalobby.org/java/forums/t44746.html - A Quick Journey Through Spring AOP
4. http://www.mularien.com/blog/2008/07/07/5-minute-guide-to-spring-security/ - 5 Minute Guide To Spring Security

OGNL:

1. http://www.ognl.org/2.6.9/Documentation/pdf/LanguageGuide.pdf
2. http://struts.apache.org/2.0.14/docs/ognl-basics.html

Struts 2.0:

1. http://struts.apache.org/2.0.6/docs/ui-tag-reference.html
2. http://struts.apache.org/2.x/docs/other-resources.html

iBatis :

1. http://ibatisnet.sourceforge.net/DevGuide.html
2. http://www.javalobby.org/java/forums/t75161.html
3. http://ibatisnet.sourceforge.net/DevGuide/ar01s04.html
4. http://opensource.atlassian.com/confluence/oss/display/IBATIS/Index

Sitemesh:

1. http://www.rkcole.com/articles/other/SiteMeshDecorators.html - Demo App
2. http://www.onjava.com/pub/a/onjava/2004/09/22/sitemesh.html - Article

Hibernate 3:

1. http://www.hibernate.org/hib_docs/reference/en/html/index.html

Freemarker:

1. http://freemarker.sourceforge.net/docs

Sunday, May 24, 2009

Eclipse Startup Error




When I start eclipse, sometimes it does not start and throws error message like "An error has occured. See the log file ..\workspace\.metadata\.log".

.log
!ENTRY org.eclipse.core.resources 2 10035 2009-05-25 10:49:07.164!MESSAGE A workspace crash was detected. The previous session did not exit normally.
!ENTRY org.eclipse.osgi 4 0 2009-05-25 10:49:07.383!MESSAGE An error occurred while automatically activating bundle org.eclipse.core.resources (39).!STACK 0org.osgi.framework.BundleException: Exception in org.eclipse.core.internal.compatibility.PluginActivator.start() of bundle org.eclipse.core.resources. at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:1010)
.....
Caused by: org.eclipse.core.internal.dtree.ObjectNotFoundException: Tree element /Test/Person.class not found. at org.eclipse.core.internal.dtree.AbstractDataTree.handleNotFound(AbstractDataTree.java:257) at org.eclipse.core.internal.dtree.DeltaDataTree.getData(DeltaDataTree.java:585) at org.eclipse.core.internal.dtree.DataDeltaNode.asBackwardDelta(DataDeltaNode.java:50) at org.eclipse.core.internal.dtree.NoDataDeltaNode.asBackwardDelta(NoDataDeltaNode.java:59) at org.eclipse.core.internal.dtree.DataDeltaNode.asBackwardDelta(DataDeltaNode.java:47) at org.eclipse.core.internal.dtree.DeltaDataTree.asBackwardDelta(DeltaDataTree.java:88)
..........
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:985) ... 28 moreRoot exception:org.eclipse.core.internal.dtree.ObjectNotFoundException: Tree element /Test/Person.class not found. at org.eclipse.core.internal.dtree.AbstractDataTree.handleNotFound(AbstractDataTree.java:257) at org.eclipse.core.internal.dtree.DeltaDataTree.getData(DeltaDataTree.java:585)
.........
at org.eclipse.core.launcher.Main.main(Main.java:952)
!ENTRY org.eclipse.osgi 4 0 2009-05-25 10:49:07.383!MESSAGE Application error!STACK 1java.lang.NoClassDefFoundError: org/eclipse/core/resources/IContainer at org.eclipse.ui.internal.ide.IDEApplication.run(IDEApplication.java:96)
..........
!ENTRY org.eclipse.osgi 2 0 2009-05-25 10:49:07.493!MESSAGE The following is a complete list of bundles which are not resolved, see the prior log entry for the root cause if it exists:!
SUBENTRY 1 org.eclipse.osgi 2 0 2009-05-25 10:49:07.493!MESSAGE Bundle update@plugins/org.eclipse.core.filesystem.linux.x86_1.0.0.v20060603.jar [32] was not resolved.
!SUBENTRY 1 org.eclipse.osgi 2 0 2009-05-25 10:49:07.493!MESSAGE Bundle update@plugins/org.eclipse.core.filesystem.macosx_1.0.0.v20060603.jar [33] was not resolved.
!SUBENTRY 1 org.eclipse.osgi 2 0 2009-05-25 10:49:07.493!MESSAGE Bundle update@plugins/org.eclipse.jdt.launching.macosx_3.1.100.v20060605.jar [95] was not resolved.!
SUBENTRY 1 org.eclipse.osgi 2 0 2009-05-25 10:49:07.493!MESSAGE Bundle update@plugins/org.eclipse.swt.carbon.macosx_3.2.2.v3236.jar [179] was not resolved.!
SUBENTRY 1 org.eclipse.osgi 2 0 2009-05-25 10:49:07.493!MESSAGE Bundle update@plugins/org.eclipse.swt.gtk.linux.x86_3.2.2.v3236.jar [180] was not resolved.!
SUBENTRY 1 org.eclipse.osgi 2 0 2009-05-25 10:49:07.493!MESSAGE Bundle update@plugins/org.eclipse.ui.carbon_3.2.0.I20060605-1400.jar [192] was not resolved.!
SUBENTRY 1 org.eclipse.osgi 2 0 2009-05-25 10:49:07.493!MESSAGE Bundle update@plugins/org.eclipse.update.core.linux_3.2.0.v20060605.jar [212] was not resolved.

How to Resolve
Delete the following files/folders:
1. \workspace\.metadata\.plugins\org.eclipse.core.resources\.snap
2. \workspace\.metadata\.plugins\org.eclipse.core.resources\.root\.markers.snap

Now start eclipse. It should start else problem is something else.

Friday, May 22, 2009

How to integrate: Struts 2+Spring+iBatis (NetBeans 6.5)





Assignment: Use Struts2/Spring/Hibernate framework to Authenticate user credential i.e. username and password. If Authentication is success then render result like “User logged successfully.” else remain in the same Login Input form.

Solution: To achieve the above assignment, I am using NetBeans 6.5 IDE and other mentioned framework and supporting libraries.

Framework:
MVC - Struts 2
Bussiness Layer - Spring 2.5
Persistance - iBatis
IDE - Netbeans 6.5
Plug-ins - Struts 2 – spring - plugin


Create Project and Add supporting Libraries:

Step 1:
Open NetBeans 6.5

Step 2:
Select File > New Project > Select the following Options
Categories: Java Web
Projects: Web Application

Step 3:
Once Java Web and Web Application are selected then Select Next (Ref. Figure 1)



Figure 1



Step 4:

Provide the following details in Name and Location Screen:
Project Name:
Project Location:

Step 5:

Select the following options in Server and Settings Screen:
Server : Tomcat 6.0 (For me it’s Tomcat 6.0)
Java EE Version : Java EE 5
Context Path : ssidemo


Step 6: Tick the check box for the following Frameworks:



Figure 2

Step 7:

IDE will add couple of jar files related spring/struts 2. Apart from that Add the following jar files in the Libraries:

1. struts2-spring-plugin-2.0.12.jar
2. commons-dbcp-1.2.1.jar
3. commons-pool-1.2.jar
4. commons-collections-3.0.jar
5. Java DB Driver - derby.jar
6. Java DB Driver - derbyclient.jar
7. Java DB Driver - derbynet.jar

(You can get 1….4 jar files by a quick search and download and 5, 6, 7 jar files is available in JDK/NetBeans)

Note:
Select Library folder and right click on it or other way and select “Add Library” and select “Java DB Driver” library to add To add jar files select “Add Jar/Folder” and select the jar files (1….4) to add

Configure Framework and Create Project Folder structure for the Assignment:

Project Folder Structure created by IDE:

Web Pages - It stores the entire files/resourced required for web app deployment
Configuration Files - All the config (.xml) files
Server Resources - Not in use for this exercise
Source Packages - Java Source Code
Test Packages - Not in use for this exercise
Libraries - All the jar/zip files
Test Libraries - Not in use for this exercise

Development Folder Structure used for this Assignment:

Struts Action - com.hcl.action
DAO - com.hcl.dao
Service - com.hcl.service
Model - com.hcl.model
JSP Pages - WEB-INF/jsp

Register Spring Details in 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/applicationContext.xml</param-value>
</context-param>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>


Do not worry about this web.xml; our IDE is smart enough to create it. But ensure that these are not missing.

Configure Hibernate / Datasource / Transaction / Struts Action with spring

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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.0.xsd">
<!—REGISTER STRUTS ACTION -->
<bean id="action.Login" class="com.hcl.action.Login" scope="prototype">
<property name="daoService" ref="service.DAOServiceBean"/>
</bean>
<!—REGISTER IBATIS FACTORY BEAN -->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation"
value="classpath:/sql-map-config.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
<!—REGISTER DATASOURCE -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver" />
<property name="url" value="jdbc:derby://localhost:1527/DEMODB" />
<property name="username" value="DEMODB" />
<property name="password" value="DEMODB" />
</bean>
<!—REGISTER DATASOURCE WITH IBATIS-->
<bean id="sqlMap" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="classpath:/sql-map-config.xml"/>
<property name="dataSource" ref="dataSource" />
</bean>
 
<!—REGISTER DATASOURCE WITH TRANSACTION MANAGER -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<alias name="txManager" alias="transactionManager" />
<bean id="DAOIntfBean" class="com.hcl.dao.DAOImpl">
<property name="sqlMapClient" ref="sqlMapClient" />
</bean>
<bean id="service.DAOServiceBean" class="com.hcl.service.DAOServiceImpl">
<property name="daoInft" ref="DAOIntfBean"/>
</bean>
</beans>

Little big than web.xml but logically very memorable.

Struts configuration

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<constant name="struts.action.extension" value="action"/>
<include file="example.xml"/> <!—ADDED BY IDE NOT IN USE FOR THIS-->
<!-- Configuration for the default package. -->
<package name="default" extends="struts-default">
<action name="Login" class="action.Login" method="doLogin">
<result name="login">/jsp/Login.jsp</result>
<result name="input">/jsp/Login.jsp</result>
<result name="error">/jsp/Login.jsp</result>
<result name="success">/jsp/Success.jsp</result>
</action>
</package>
</struts>


Here “action.Login” is a bean defined in ApplicationContext.xml

Configure SQL Queries with iBatis

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<settings
cacheModelsEnabled="true"
enhancementEnabled="true"
maxSessions="64"
maxTransactions="8"
maxRequests="128"
/>
<sqlMap resource="UserDetails.xml"/>
</sqlMapConfig>

Here UserDetails.xml contains the queries used for my purpose.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap>
<resultMap id="model.UserInfo" class="com.hcl.model.UserInfo">
<result property="userName" column="USER_NAME"/>
<result property="password" column="PASSWORD"/>
</resultMap>
<select id="isUserExists" parameterClass="com.hcl.model.UserInfo" resultClass="Integer">
SELECT count(*)
FROM USER_INFO
WHERE USER_NAME=#userName# AND PASSWORD = #password#
</select>
</sqlMap>


It is not a best way to do; you have better way to do it. But for demo there is no problem.

Java Code

Login.java

package com.hcl.action;

import com.hcl.model.UserInfo;
import com.hcl.service.DAOServiceIntf;
import com.opensymphony.xwork2.ActionSupport;

public class Login extends ActionSupport {

private DAOServiceIntf DaoService;
private String userName;
private String password;


public Login() {
}

public String doLogin() throws Exception {
UserInfo userInfo = new UserInfo();
userInfo.setPassword(password);
userInfo.setUserName(userName);
if(DaoService.isUserExists(userInfo)){
return ActionSupport.SUCCESS;
}else{
return ActionSupport.INPUT;
}

}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public DAOServiceIntf getDaoService() {
return DaoService;
}

public void setDaoService(DAOServiceIntf DaoService) {
this.DaoService = DaoService;
}
}

Login-validation.xml – Way to do Validation in Struts 2

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="userName">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>Login name is required</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>Password is required</message>
</field-validator>
</field>
</validators>

UserInfo.java

package com.hcl.model;

public class UserInfo {

private String userName;
private String password;

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}
}

DAOIntf.java (DAO Interface)

package com.hcl.dao;

import com.hcl.model.UserInfo;

public interface DAOIntf {
public boolean isUserExists(UserInfo userInfo);
}


DAOImpl.java (DAO Implementation)

package com.hcl.dao;
import com.hcl.model.UserInfo;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

public class DAOImpl extends SqlMapClientDaoSupport implements DAOIntf {

public boolean isUserExists(UserInfo userInfo) {
Integer userCount;
boolean result = false;
try{
userCount =(Integer) getSqlMapClientTemplate().queryForObject("isUserExists",userInfo);
}
catch(Exception ex){
ex.printStackTrace();
System.out.println(ex);
return false;
}
if (userCount != null && userCount > 0) {
result = true;
} else{
result = false;
}
return result;
}
}

DAOServiceIntf.java (Service Interface)

package com.hcl.service;

import com.hcl.model.UserInfo;

public interface DAOServiceIntf {
public boolean isUserExists(UserInfo userInfo);
}

DAOServiceImpl.java (Service Implementation)

package com.hcl.service;

import com.hcl.dao.DAOIntf;
import com.hcl.model.UserInfo;

public class DAOServiceImpl implements DAOServiceIntf {

private DAOIntf daoInft;

public boolean isUserExists(UserInfo userInfo){
return daoInft.isUserExists(userInfo);
}

public DAOIntf getDaoInft() {
return daoInft;
}

public void setDaoInft(DAOIntf daoInft) {
this.daoInft = daoInft;
}
}


Result (JSP) Pages

Login.jsp


<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<s:form name="LoginForm" action="Login" method="post" >
<table>
<tr>
<td>
<s:text name="User Name :"/>
</td>
<td>
<s:textfield name="userName" />
</td>
</tr>
<tr>
<td>
<s:text name="Password :"/>
</td>
<td>
<s:password name="password"/>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<s:submit name="Login" value="Login" align="center"/>
</td>
</tr>
</table>
</s:form>
</body>
</html>

Success.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
User <s:property value="userName"/> logged successfully.
</body>
</html>

Deployment Folder Structure ( NetBeans 6.5 IDE takes care most of the file location. )

Java Source Code: No need to place class/jar files in WEB-INF/classes or WEB-INF/lib. IDE takes care about it.
xml Files:



If everything goes fine then: URL To Access web Application:

http://localhost:8080/ssi/jsp/Login.jsp