Friday, March 14, 2008

Struts+Hibernate+oracle9idb

Started to workout on a sample setup of our Ebms application. Initially i thought it would be easy. Later found out bit troublesome.

For compilation

1. To compile thru build.xml in jdeveloper All the jar's except log4j.jar should be available under <EBMS_HOME>EBMSProj\public_html\WEB-INF\lib.

2. To compile thru jdeveloper All the jar's INCLUDING log4j.jar should be available under <EBMS_HOME>EBMSProj\public_html\WEB-INF\lib.

3. During run for logging purpose log4j.jar may be needed. So it should be placed under <TOMCAT_HOME>/WEBAPPS/EBMS/WEB-INF/lib

4. To Generate the DTO class from hbm.xml files which will be available under com/ebms/dao please use the ant build.xml task doHibernateTask


5. When try to run a hibernate sample in jdeveloper oc4j, the following exception occurred. I hope this error wont happen in tomcat.

-----------------------
org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken [from com.ebms.dao.Employee as e where e.empname = (:paramA)]
at org.hibernate.hql.ast.HqlLexer.panic(HqlLexer.java:57)
at antlr.CharScanner.setTokenObjectClass(CharScanner.java:239)
at org.hibernate.hql.ast.HqlLexer.setTokenObjectClass(HqlLexer.java:31)
at antlr.CharScanner.<init>(CharScanner.java:40)
at antlr.CharScanner.<init>(CharScanner.java:49)
at org.hibernate.hql.antlr.HqlBaseLexer.<init>(HqlBaseLexer.java:56)
----------------------------
Solution to avoid the above error is by adding a property in hibernate.cfg.xml file as below

<property name="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</property>

========================================================================================================================================================


6.
PROBLEM:
-------
In struts-config (1.2.8 version) we used to use the <forward> tag like this...<forward name="success" path="cust.search.personal.Reg"/>
When used such tag with Struts 1.3.8 version, it throwed as below.

2008-02-22 17:45:24,609, WARN [http-8083-Processor25] org.apache.struts.chain.commands.AbstractExceptionHandler - Unhandled exception
java.lang.IllegalArgumentException: Path cust.search.personal.Reg does not start with a "/" character
at org.apache.catalina.core.ApplicationContext.getRequestDispatcher(ApplicationContext.java:377)


SOLUTION
--------
Pls refer the upgrade notes at http://wiki.apache.org/struts/StrutsUpgradeNotes12to13
Pls refer the 1.2 and 1.3 DTD's difference at http://people.apache.org/~wsmoak/struts/struts-config-diff.html

It was instructed to use the below chainconfig entry in web.xml file

<init-param>
<param-name>chainConfig</param-name>
<param-value>org/apache/struts/tiles/chain-config.xml</param-value>
</init-param>

Once added the problem is gone.

========================================================================================================================================================

7.
PROBLEM:
-------

javax.servlet.jsp.JspException: Missing message for key "cust.details" in bundle "(default bundle)" for locale en_US

SOLUTION:
-------
Check in web.xml file the below entry is available and it should be the first entry before struts-config entry.
Pls chk a sample EBMS web.xml entry at the bottom of this readme.txt file under "OUR EBMS WEB.XML ENTRIES"


<init-param>
<param-name>application</param-name>
<param-value>com.ebms.ApplicationResources</param-value>
</init-param>

========================================================================================================================================================
8.
PROBLEM:
-------
In jdeveloper when <bean:message key="cust.pers.firstName"/> is added thru IDE's bean tag, some <bean:message/> entries get added automatically
to CustomerTabs.jsp which is the master screen for CustomerSearch and Personal tab (Which is a tabbed screen). If the problem persists check is there
any empty <bean:message /> tags in the related jsp's.

Exception scenario 1
-------------------
java.lang.NullPointerException: Attribute name is null
at com.evermind[Oracle Containers for J2EE 10g (11.1.1.0.0) ].server.http.EvermindPageContext.findAttribute(EvermindPageContext.java:237)
at org.apache.struts.taglib.TagUtils.lookup(TagUtils.java:824)
at org.apache.struts.taglib.TagUtils.lookup(TagUtils.java:858)
at org.apache.struts.taglib.bean.MessageTag.doStartTag(MessageTag.java:206)
at _html__tabs._customer._CustomerTabs._jspService(_CustomerTabs.java:141)
[/html_tabs/Customer/CustomerTabs.jsp]


Exception Scenarion 2
---------------------
org.apache.struts.chain.commands.ExceptionCatcher - Exception from exceptionCommand 'servlet-exception'
javax.servlet.ServletException: javax.servlet.jsp.JspException: ServletException in '/copyright.jsp': Null attribute name
at org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:844)
at org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:781)
at org.apache.jsp.layouts.layout_jsp._jspService(org.apache.jsp.layouts.layout_jsp:166)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)


SOLUTION:
--------
for both exception scenario Just remove any empty tags like below in those screens and its related screens. Chk the message carefull.
for Ex. in the Exception Scenario you can see "ServletException in '/copyright.jsp': Null attribute name"
In that case go to such files and remove empty bean or any other tags which is not relevant there.

<bean:message/>
<bean:message/>
<bean:message/>


========================================================================================================================================================

9:
PROBLEM:
-------

[hibernatetool] org.hibernate.MappingException: An association from the table EM
PLOYEE refers to an unmapped class: com.ebms.dao.Brokerstaff


SOLUTION:
--------
Check whether all the ***.hbm.xml(Ex. Employee.hbm.xml) files have been declared in ***.cfg.xml (hibernate.cfg.xml)

Ex. <mapping resource="com/ebms/dao/Brokerstaff.hbm.xml"/>

========================================================================================================================================================

10. PROBLEM:
-------
2008-03-15 12:16:17,046, ERROR [http-8083-Processor23] org.hibernate.LazyInitializationException - could not initialize proxy - no Session
org.hibernate.LazyInitializationException: could not initialize proxy - no Session


ORM MAPPINGS:
------------
<!-------------------------------- BEGIN EMPLOYEE.HBM.XML -------------------------------------->
<hibernate-mapping>
<class name="com.ebms.dao.Employee" table="EMPLOYEE">

<id name="txtFldempid" type="java.lang.String" column="EMPID">
<generator class="assigned" />
</id>

<property name="txtFldempName" type="java.lang.String" column="EMP_NAME" not-null="true" length="60" />

<!-- bi-directional many-to-one association to Stafflevel -->
<many-to-one
name="selstafflevel"
class="com.ebms.dao.Stafflevel"
not-null="true">

<column name="LEVEL_CODE" />
</many-to-one>

<!-- bi-directional many-to-one association to Empstatus -->
<many-to-one
name="selempstatus"
class="com.ebms.dao.Empstatus"
not-null="true">

<column name="EMPLOYMENT_STATUS" />
</many-to-one>
</class>
</hibernate-mapping>

<!-------------------------------- END EMPLOYEE.HBM.XML ----------------------------------------->

<!--------------------------------------BEGIN STAFFLEVEL.HBM.XML -------------------------------->
<hibernate-mapping>
<class name="com.ebms.dao.Stafflevel" table="STAFFLEVEL">

<id
name="txtFldlevelcode"
type="java.lang.String"
column="LEVELCODE">

<generator class="assigned" />
</id>

<property
name="txtFldlevelname"
type="java.lang.String"
column="LEVELNAME"
not-null="true"
length="60"/>

<set
name="employees"
lazy="true"
inverse="true"
cascade="none">
<key>
<column name="LEVEL_CODE" />
</key>
<one-to-many class="com.ebms.dao.Employee"/>
</set>

</class>
</hibernate-mapping>

<!----------------------------------- END OF STAFFLEVEL.HBM.XML --------------------------------->

<!----------------------------------- BEGIN EMPSTATUS.HBM.XML ----------------------------------->

<hibernate-mapping>
<class name="com.ebms.dao.Empstatus" table="EMPSTATUS">

<id
name="txtFldempstatuscode"
type="java.lang.String"
column="EMPSTATUSCODE">
<generator class="assigned" />
</id>

<property
name="txtFldempstatusname"
type="java.lang.String"
column="EMPSTATUSNAME"
not-null="true"
length="60" />

<set
name="employees"
lazy="true"
inverse="true"
cascade="none">
<key>
<column name="EMPLOYMENT_STATUS" />
</key>
<one-to-many
class="com.ebms.dao.Employee"/>
</set>

</class>
</hibernate-mapping>

<!----------------------------------- END OF EMPSTATUS.HBM.XML --------------------------------->

PROBLEM QUERY :- WHEN THIS QUERY EXECUTED "LazyInitializationException - could not initialize proxy - no Session" ERROR HAPPEND
-------------

public static final String HQL_TAB_FIND_ELEMENT =
"from com.ebms.dao.Employee e " +
"where upper(e.txtFldempid) like upper((:paramA)) ";


MODIFIED THE ABOVE PROBLEM QUERY:-
---------------------------------
public static final String HQL_TAB_FIND_ELEMENT =
"from com.ebms.dao.Employee e left join fetch e.selempstatus stat " +
"where upper(e.txtFldempid) like upper((:paramA)) ";// left join fetch e.selcustCompany ";


List<Employee> elements = new ArrayList<Employee>();//1.5 Generics arraylist declaration
session = factory.openSession();
Query q = session.createQuery(HQL_TAB_FIND_ELEMENT);
q.setParameter("paramA", strEmpId, Hibernate.STRING);
//q.setParameter("paramB", strCompId, Hibernate.STRING);

elements = q.list();


1.REASON MAY BE:-
-----------------
When retrieving from elements List object, the "empObj.getSelempstatus()" was referred unnecessarily many times to check
whether it is null, which looses session to retrieve empstatus from Employee which has foreign key reference to EmpStatus class from Employee.hbm.xml.


fplog.info("------ 444 "+empObj.getSelempstatus());
fplog.info("------ 444 "+empObj.getSelempstatus().getTxtFldempstatuscode());
fplog.info("gggggggg");
strBuf.append(" selFormempstatusid = '"+Utility.forXML((Utility.checkNullVal(empObj.getSelempstatus()) ? EBMSConstants.STR_NULL_STRING : empObj.getSelempstatus().getTxtFldempstatuscode()))+"' ");



2. REASON MAY BE:-
------------
Though there is unnecessary references to getempstatus as above log entries
fplog.info("------ 444 "+empObj.getSelempstatus());

Even if the first log line is commented out //fplog.info("------ 444 "+empObj.getSelempstatus());
it works fine or whatever the unnessary log entries are there, if the MODIFIED THE ABOVE PROBLEM QUERY which uses LEFT JOIN FETCH syntax
to fetch the empstatus in the same query, the problem gets solved.

========================================================================================================================================================


11.PROBLEM:-
-------

2008-03-14 16:34:23,953, INFO [http-8083-Processor23] com.ebms.DB.CustomerDB - @ deleteDBCustomer
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.ebms.dao.Stafflevel
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:219)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:397)
at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:241)
at org.hibernate.type.TypeFactory.findDirty(TypeFactory.java:597)
at org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:3123)



PROBLEM SOURCE:-
-----------------

public void deleteDBCustomer(SessionFactory factory,
Employee empl) throws HibernateException{

Session session = factory.openSession();
Transaction tx = session.beginTransaction();
try{
fplog.info("delete db ");
session.delete(empl);
tx.commit();
fplog.info("transaction commit ");
}catch(HibernateException he) {
fplog.info("@ deleteDBCustomer ",he);
if (tx!=null) tx.rollback();
}
finally{
fplog.info("@ deleteDBCustomer finally block");
session.close();
}
}//end of updateDBCustomer




SOLUTION:-
---------

fplog.info("delete db ");

//session.delete(empl);
Object obj = session.load(Employee.class,empl.getTxtFldempid());
session.delete(obj);
tx.commit();
fplog.info("transaction commit ");



========================================================================================================================================================






















OUR EBMS WEB.XML ENTRIES
------------------------

<?xml version = '1.0' encoding = 'windows-1252'?>
<web-app 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" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
<description>Empty web.xml file for Web Application</description>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>application</param-name>
<param-value>com.ebms.ApplicationResources</param-value>
</init-param>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>chainConfig</param-name>
<param-value>org/apache/struts/tiles/chain-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>CustServlet</servlet-name>
<servlet-class>com.ebms.servlets.CustServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>CustServlet</servlet-name>
<url-pattern>/custservlet</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>35</session-timeout>
</session-config>
<mime-mapping>
<extension>html</extension>
<mime-type>text/html</mime-type>
</mime-mapping>
<mime-mapping>
<extension>txt</extension>
<mime-type>text/plain</mime-type>
</mime-mapping>
<jsp-config/>
</web-app>