Archive for the ‘Java’ Category

Hibernate: Supporting Spring DataSourceTransactionManager (and @Transactional) programmatically with SessionFactoryUtils

Sunday, July 5th, 2009

Here is the minimum code to support DataSourceTransactionManager thread bound session  (similar to OpenSessionInViewInterceptor).

For each thread:

public void beginThreadSession(SessionFactory sessionFactory){

  Session session = SessionFactoryUtils.getSession(sessionFactory, true);
  TransactionSynchronizationManager.bindResource(sessionFactory,
                                               new SessionHolder(session));

}
public void endThreadSession(SessionFactory sessionFactory){

  SessionHolder sessionHolder =
    (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
  SessionFactoryUtils.closeSession(sessionHolder.getSession());

}

DataSourceTransactionManager will pickup the thread bound session with SessionFactoryUtils. The trick is calling the “un/bindResource” methods. This set one session for all your requests and transactions for a given thread (and use the @transactional if you have configured it as follow).

<aop:config proxy-target-class="true"/>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/>
    <property name="configLocation" value="config/hibernate.cfg.xml"/>
    <property name="dataSource" ref="dataSource"/>
</bean>

<tx:annotation-driven transaction-manager="txManager"/>

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

Obviously, this is the strict minimum code (good of unit testing for example). For Web App, use the OpenSessionInViewInterceptor.

<bean id="openSessionInView"
class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
    <property name="sessionFactory" ref="sessionFactory"/>
    <!-- optional
    <property name="flushModeName" value="FLUSH_NEVER" />
    -->
</bean>

Hibernate: org.hibernate.WrongClassException … instanceAlreadyLoaded

Monday, May 4th, 2009

Hibernate inheritance and relationship could lead to the following exception:

Caused by: org.hibernate.WrongClassException: Object with id: 3 was not of the
specified subclass...
...
        at org.hibernate.loader.Loader.instanceAlreadyLoaded(Loader.java:1267)
        at org.hibernate.loader.Loader.getRow(Loader.java:1219)
        at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:603)
        at org.hibernate.loader.Loader.doQuery(Loader.java:724)
...

Putting @ForceDiscriminator near the @DiscriminatorValue(..) of your respective classes might solve the problem.
See Hibernate Annotation Doc

Java: c3p0.ComboPooledDataSource broken pipe Error With MySQL

Monday, April 13th, 2009

This usually happen when the client connection pool maintained connection longer than the database connection. Fix: set the maxIdleTime property:

 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
  <property name="driverClass" value="${db.driverClass}" />
  <property name="jdbcUrl" value="${db.jdbcUrl}" />
  <property name="user" value="${db.user}" />
  <property name="password" value="${db.password}" />
  <!-- 1/2 hr. MySQL server default connection timeout is 43200 (12hrs) -->
  <property name="maxIdleTime" value="1800" />
 </bean>

Information Source: Broken pipe

Java: JODConverter 3.x Getting Started

Thursday, April 9th, 2009

Requirements:

  • OpenOffice installed and OpenOffice started (e.g., OpenOffice in the system tray on Windows)
  • Java

Quick steps to test:

  1. Download the latest JODConverter 3.x from google code.
  2. Unzip the jar file
  3. Do a quick test:
    java -jar lib/jodconverter-${version}.jar test.odt test.pdf
  4. you should see something like
    C:\apps\jodconverter-3.0-beta-1>java -jar lib/jodconverter-3.0-beta-1.jar test.odt test.pdf
    
    Apr 9, 2009 12:56:42 PM net.sf.jodconverter.office.OfficeProcess start
    INFO: starting process with acceptString 'socket,host=127.0.0.1,port=8100' and
    profileDir 'C:\Users\JEREMY~1\AppData\Local\Temp\.jodconverter_socket_host-127.0.0.1_port-8100'
    Apr 9, 2009 12:56:42 PM net.sf.jodconverter.office.OfficeProcess start
    INFO: started process; pid -1
    Apr 9, 2009 12:56:47 PM net.sf.jodconverter.office.OfficeConnection connect
    INFO: connected: 'socket,host=127.0.0.1,port=8100'
    Apr 9, 2009 12:56:52 PM net.sf.jodconverter.office.OfficeConnection$1 disposing
    INFO: disconnected: 'socket,host=127.0.0.1,port=8100'
    Apr 9, 2009 12:56:53 PM net.sf.jodconverter.office.ManagedOfficeProcess doEnsureProcessExited
    INFO: process exited with code 0

Note: As you can see it works because it assumes that OpenOffice listen to the port 8100, which happen to be the case (how lucky!).

In a Java (Server) App:

  1. Copy the following .jar files in your webapp lib directory
    lib/jodconverter-3.0-beta-1.jar
    lib/juh-3.0.0.jar
    lib/jurt-3.0.0.jar
    lib/ridl-3.0.0.jar
    lib/unoil-3.0.0.jar
  2. Use the following code snippet:
    OfficeManager officeManager = new ManagedProcessOfficeManager();
    officeManager.start();
    
    OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);
    converter.convert(sourceFile,targetFile);
    
    officeManager.stop();

Best Practice (from JODConverter group)

  1. OfficeManager instance can and should be shared across all
    threads
    . It should typically be started when your webapp starts, and
    stopped when the webapp stops. It can be e.g. a singleton, or a Spring
    bean, or other equivalent approach of your choice.
  2. The OfficeDocumentConverter instance can also be shared, or you can
    create a different instance per thread. It doesn’t really matter,
    since all conversions will be delegated to the OfficeManager anyway.

See Also

RegEx: Java Quick Start and Tips

Wednesday, April 8th, 2009

Java: Word, RTF, PDF convert, read, import, export, write

Tuesday, April 7th, 2009

Reading/Writing Word and PDF document could be quite tricky.

For Word (.doc), the best option seems to be using OpenOffice to convert the file to a text format (RTF or OpenOffice XML format), modify the text document, and use OpenOffice to convert back to .doc. JODConverter 3.x seems to be a great option for doing that in a Web Application.

For PDF, iText seems to be the solution.

There seems to be also a very complete and mature commercial product for Java which is Aspose. It supports direct access to Office documents such as .doc file allowing to preserve any meta data such as revision and such. Its a little pricey but manageable for a SaaS application, although, I am not sure how their definition of “location” applies to a SaaS application.

Here are some pointers:

Word:

RTF:

PDF:

  • IText (download): Java Lib to read/create PDF document.
  • FOP: reads a formatting object (FO) tree and renders the resulting pages to a specified output (The primary output target is PDF)

Java: Servlet Set Expires Header with Cache Control

Saturday, March 28th, 2009

When setting the expires date in Servlet, better to set the cache-control as well.

final int CACHE_DURATION_IN_SECOND = 60 * 60 * 24 * 2; // 2 days
final long   CACHE_DURATION_IN_MS = CACHE_DURATION_IN_SECOND  * 1000;
long now = System.currentTimeMillis();
//res being the HttpServletResponse of the request
res.addHeader("Cache-Control", "max-age=" + CACHE_DURATION_IN_SECOND);
res.addHeader("Cache-Control", "must-revalidate");//optional
res.setDateHeader("Last-Modified", now);
res.setDateHeader("Expires", now + CACHE_DURATION_IN_MS);

For no cache

res.setHeader("Pragma", "No-cache");
res.setHeader("Cache-Control", "no-cache,no-store,max-age=0");
res.setDateHeader("Expires", 1);

Hibernate (annotation): Error: TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing

Friday, March 27th, 2009

If you get an error like this one

Hibernate: Error: TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing..

It is probably because you did not annotate your ManyToOne with the Hibernate SAVE_UPATE Cascade annotation:

@ManyToOne()
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
public Category getCategory() {
        return category;
}

Note, putting only

@ManyToOne(cascade = {CascadeType.MERGE,CascadeType.PERSIST})
public Category getCategory() {

Will not resolve the issue.

Java: Hibernate 3.4 and SLF4J Impl Class not found and Singleton error

Friday, March 20th, 2009

Hibernate 3.4 does not have a SLF4J implementation, and if you download the latest implementation from http://www.slf4j.org/download.html you will get an imcompatible impl version (1.5.6 impl with the 1.5.2 api from Hibernate).

Just do the following:

  1. Remove all slf4j*.jar from your lib.
  2. Add the the latest sfl4j-api (i.e. slf4j-api-1.5.2)
  3. Add the latest impl slf4j-log4j12-1.5.6-.jar

NOTE: If you use Hibernate, make sure to use the slf4j-log4j*.jar, otherwise, changing the log4j.properties will have no effect. (see Turn off logging from log4j and slf4j)

Java: ActiveMQ in-VM Configuration, Initialization, and Usage

Saturday, January 24th, 2009

Creating a Connection Factory (Programmatic):

import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.Connection;
import javax.jms.Session;
...
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost");
...
Connection connection = factory.createConnection();
...
connection.start();
...
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);