Archive

Archive for the ‘Java’ Category

JPA with UUID

June 12th, 2013 No comments

I wanted to have a data package containing only JPA annotations.

I created a base class specifying the keytype (I use UUID and Long based Entities):

package com.famvdploeg.data;
 
import java.io.Serializable;
 
/**
 * Absolute base class for persistable classes.
 * Contract forces get and set methods for id.
 * @author wytze
 * @param <KeyType>
 */
public abstract class Persistable<KeyType extends Serializable> {
	public abstract KeyType getId();
 
	public abstract void setId(KeyType id);
}
package com.famvdploeg.data;
 
import java.util.UUID;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
 
@MappedSuperclass
public abstract class UuidBasedEntity extends Persistable<UUID> {
 
	@Id
	private UUID id;
 
	@Override
	public UUID getId() {
		return id;
	}
 
	@Override
	public void setId(UUID id) {
		this.id = id;
	}
}

Sample entity:

package com.famvdploeg.data;
 
import java.io.Serializable;
import java.util.UUID;
import javax.persistence.Entity;
 
@Entity
public class Sample extends UuidBasedEntity implements Serializable {
 
	private String someExampleProperty;
 
        /* ... getters and setters */
}

All these entities go in one separate jar.

Next I create another package using the entity jar.

package com.famvdploeg.dao;
 
import com.famvdploeg.data.Persistable;
import java.io.Serializable;
 
public interface GenericRepository<Entity extends Persistable> {
	public void persist(Entity e);
	public Entity findById(Serializable id);
	public void merge(Entity t);
	public void remove(Serializable id);
	public Entity saveOrUpdate(Entity entity);
}

And a generic implementation of this dao: (Spring is used to inject the persistencecontext)

package com.famvdploeg.dao.jpa;
 
import java.io.Serializable;
import com.famvdploeg.dao.GenericRepository;
import com.famvdploeg.data.Persistable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
 
public class GenericJpaRepository<Entity extends Persistable> implements GenericRepository<Entity> {
 
	@PersistenceContext
	protected EntityManager em;
 
	@Override
	public void persist(Entity e) {
		em.persist(e);
	}
 
	@Override
	public Entity findById(Serializable id) {
		return em.find(returnEntityClass(), id);
	}
 
	@Override
	public void merge(Entity e) {
		em.merge(e);
	}
 
	@Override
	public void remove(Serializable id) {
		em.remove(findById(id));
	}
 
	@Override
	public void flush() {
		em.flush();
	}
 
	@Override
	public Entity saveOrUpdate(Entity entity) {
		if (entity.getId() == null) {
			em.persist(entity);
			return entity;
		} else {
			return em.merge(entity);
		}
	}
 
	protected List<Entity> findAll() {
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<Entity> cq = cb.createQuery(returnEntityClass());
 
		return em.createQuery(cq).getResultList();
	}
 
	protected Entity findByProperty(String property, Object value) {
		try {
			return em.createQuery(createQueryByProperty(property, value)).getSingleResult();
		} catch (NoResultException ex) {
			return null;
		}
	}
 
	protected List<Entity> findAllByProperty(String property, Object value) {
		return em.createQuery(createQueryByProperty(property, value)).getResultList();
	}
 
	protected Entity findByProperties(Map<String, Object> properties) {
		try {
			return em.createQuery(createQueryByProperties(properties)).getSingleResult();
		} catch (NoResultException ex) {
			return null;
		}
	}
 
	protected List<Entity> findAllByProperties(Map<String, Object> properties) {
		return em.createQuery(createQueryByProperties(properties)).getResultList();
	}
 
	public Class<Entity> returnEntityClass() {
		ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
		return (Class<Entity>) genericSuperclass.getActualTypeArguments()[0];
	}
 
	private CriteriaQuery<Entity> createQueryByProperty(String property, Object value) {
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<Entity> cq = cb.createQuery(returnEntityClass());
		Root<Entity> root = cq.from(returnEntityClass());
		cq = cq.where(cb.equal(root.get(property), value));
		return cq;
	}
 
	private CriteriaQuery<Entity> createQueryByProperties(Map<String, Object> properties) {
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<Entity> cq = cb.createQuery(returnEntityClass());
		Root<Entity> root = cq.from(returnEntityClass());
		for (Entry<String, Object> entry : properties.entrySet()) {
			cq = cq.where(cb.equal(root.get(entry.getKey()), entry.getValue()));
		}
		return cq;
	}
}

Now I want to use hibernate to map my UUID’s as PostgreSQL uuid type. We will add a mapping to do so.

(location: com/famvdploeg/data/CustomTypes.hbm.xml, place in DAO/Repository jar)

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<!--
		http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/types.html
		Section 6.5 covers type registry and registerTypeOverride method on the Configuration object,
		typedefs are the preferred way of registering custom types
	-->
    <typedef name="java.util.UUID" class="org.hibernate.type.UUIDCharType" />
 
    <!-- 
        I want to store clob values as text and not as materialized clobs so we override that here.
        Otherwise the database will show long values when using an SQL tool to query the database.
    -->
    <typedef name="materialized_clob" class="org.hibernate.type.TextType" />
	<!-- Possible values:
	<typedef name="java.util.UUID" class="org.hibernate.type.UUIDBinaryTypee" />
	<typedef name="java.util.UUID" class="org.hibernate.type.UUIDCharType" />
	<typedef name="java.util.UUID" class="org.hibernate.type.PostgresUUIDType" />
	-->
</hibernate-mapping>

Next we fill the persistence.xml

(location: META-INF/persistence.xml)

<?xml version="1.0" encoding="UTF-8"?>
<persistence
	xmlns='http://java.sun.com/xml/ns/persistence'
	xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
	xsi:schemaLocation='http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd'
	version="2.0">
 
	<persistence-unit name="jpa-example-postgres" transaction-type="RESOURCE_LOCAL">
		<provider>org.hibernate.ejb.HibernatePersistence</provider>
 
		<class>com.famvdploeg.data.Sample</class>
 
		<properties>
			<!--<property name="hibernate.archive.autodetection" value="class, hbm"/>-->
			<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect" />
                        <!-- Use this only for testing!
			<property name="hibernate.hbm2ddl.auto" value="create-drop" />
                        -->
                        <!-- Nicer naming of tables with underscores fooName -> foo_name -->
			<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" />
 
			<!-- Connection properties, moved to datasource (@see applicationContext.xml)
			<property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/jpa_example" />
			<property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
			<property name="hibernate.connection.username" value="example" />
			<property name="hibernate.connection.password" value="example" />
			-->
 
			<!-- c3p0 connection pooling, setup when creating datasource (@see com.mchange.v2.c3p0.ComboPooledDataSource)
			<property name="hibernate.c3p0.min_size">5</property>
			<property name="hibernate.c3p0.max_size">20</property>
			<property name="hibernate.c3p0.timeout">300</property>
			<property name="hibernate.c3p0.max_statements">50</property>
			<property name="hibernate.c3p0.idle_test_period">3000</property>
			-->
		</properties>
 
                <!-- The specific mapping for UUID's is added here -->
		<mapping-file>com/famvdploeg/data/CustomTypes.hbm.xml</mapping-file>
	</persistence-unit>
</persistence>

And for completeness the applicationContext.xml for 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" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:task="http://www.springframework.org/schema/task"
 
	xsi:schemaLocation="
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
       		http://www.springframework.org/schema/tx
       		http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       		http://www.springframework.org/schema/aop
       		http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
			http://www.springframework.org/schema/task
			http://www.springframework.org/schema/task/spring-task-3.0.xsd">
 
	<!-- In production: <bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer"> -->
	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<!-- Test properties. Should be filled from Context.xml in production -->
		<property name="properties">
			<props>
				<!--
				<prop key="jpa-example-jdbc-url">jdbc:h2:mem:jpa_example</prop>
				<prop key="jpa-example-jdbc-username">sa</prop>
				<prop key="jpa-example-jdbc-password">sa</prop>
				<prop key="jpa-example-jdbc-driver">org.h2.Driver</prop>
				-->
				<prop key="jpa-example-jdbc-url">jdbc:postgresql://localhost:5432/jpa_example</prop>
				<prop key="jpa-example-jdbc-username">example</prop>
				<prop key="jpa-example-jdbc-password">example</prop>
				<prop key="jpa-example-jdbc-driver">org.postgresql.Driver</prop>
			</props>
		</property>
	</bean>
 
	<!-- Use pooled in production, @see com.mchange.v2.c3p0.ComboPooledDataSource -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="url" value="${jpa-example-jdbc-url}" />
		<property name="username" value="${jpa-example-jdbc-username}" />
		<property name="password" value="${jpa-example-jdbc-password}" />
		<property name="driverClassName" value="${jpa-example-jdbc-driver}" />
	</bean>
 
	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="persistenceUnitName" value="jpa-example-postgres" />
		<property name="dataSource" ref="dataSource" />
	</bean>
 
	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>
 
	<tx:annotation-driven transaction-manager="transactionManager" />
 
	<context:annotation-config />
</beans>

It is also possible to store the UUID as a char(36) to do this we need to change the type in the CustomTypes.hbm.xml to org.hibernate.type.UUIDCharType.
We can then modify the mapping from the data jar through adding an orm.xml to the META-INF folder. It will normally create a varchar(255) column but that is useless. We want to specify the use of an char(36) column as UUID’s are stored as Strings of a fixed length of 36 characters.

<?xml version="1.0" encoding="UTF-8"?>
 
<entity-mappings
  xmlns="http://java.sun.com/xml/ns/persistence/orm"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
  version="2.0">
 
	<package>com.famvdploeg.data</package>
 
	<mapped-superclass class="UuidBasedEntity" metadata-complete="false">
		<attributes>
			<id name="id">
				<column column-definition="char(36)" />
			</id>
		</attributes>
	</mapped-superclass>
</entity-mappings>

That’s it! Awesome! Clean separation of JPA and Hibernate.

Categories: Java Tags:

Setting up an OrientDB server on Ubuntu

January 19th, 2013 8 comments

Go to the directory you want to install OrientDB.

cd /opt

Download one of the two flavors of OrientDB (standard or graph edition). (If you don’t know which to take, pick the Graph Ed.)

sudo wget https://s3.amazonaws.com/orientdb/releases/orientdb-1.3.0.tar.gz
#sudo wget https://s3.amazonaws.com/orientdb/releases/orientdb-graphed-1.3.0.tar.gz

Unpack the file

sudo tar -zxvf orientdb-1.3.0.tar.gz

I usually remove the tar.gz file and add a symlink

sudo rm orientdb-1.3.0.tar.gz
sudo ln -s orientdb-1.3.0/ orientdb

Configure the default orientdb password. (I use vi, you use your own favorite editor ;))

sudo vi orientdb/config/orientdb-server-config.xml

Go to the section [orient-server > storages > storage] in the xml, change the default username and password and save the file

<!-- Default in-memory storage. Data are not saved permanently. -->
<storage path="memory:temp" name="temp" userName="yourUsername" userPassword="yourPassword" loaded-at-startup="true" />

Get the root password for later use or/and add your own preferred account in [orient-server > users]:
(I prefer to remove the root account and add a new one)

<user name="yourUsername" password="yourPassword" resources="*"/>

As the file is holding passwords it might be a good idea to remove the read permission for other users.

sudo chmod 640 /opt/orientdb/config/orientdb-server-config.xml

Create a user that will run the server:

# -d, --home-dir HOME_DIR       home directory of the new account
# -M, --no-create-home          do not create the user's home directory
# -r, --system                  create a system account
# -s, --shell SHELL             login shell of the new account (/bin/false =  no login)
# -U, --user-group              create a group with the same name as the user
sudo useradd -d /opt/orientdb -M -r -s /bin/false -U orientdb

Change ownership of orientdb directory/links:

sudo chown -R orientdb.orientdb orientdb*

Modify the user group rights so that users in the orientdb group can invoke shell scripts.

sudo chmod 775 /opt/orientdb/bin
sudo chmod g+x /opt/orientdb/bin/*.sh
sudo usermod -a -G orientdb yourUsername

Copy the init.d script:

sudo cp orientdb/bin/orientdb.sh /etc/init.d/

Update the init.d script with this sed script or just edit the file. (The copied one)

sudo sed -i "s|YOUR_ORIENTDB_INSTALLATION_PATH|/opt/orientdb|;s|USER_YOU_WANT_ORIENTDB_RUN_WITH|orientdb|" /etc/init.d/orientdb.sh

And change the following lines, we use sudo because our system account does not have a login shell.

# You have to SET the OrientDB installation directory here (if not already done so)
ORIENTDB_DIR="/opt/orientdb"
ORIENTDB_USER="orientdb"
 
#su -c "cd \"$ORIENTDB_DIR/bin\"; /usr/bin/nohup ./server.sh 1>../log/orientdb.log 2>../log/orientdb.err &" - $ORIENTDB_USER
sudo -u $ORIENTDB_USER sh -c "cd \"$ORIENTDB_DIR/bin\"; /usr/bin/nohup ./server.sh 1>../log/orientdb.log 2>../log/orientdb.err &"
 
#su -c "cd \"$ORIENTDB_DIR/bin\"; /usr/bin/nohup ./shutdown.sh 1>>../log/orientdb.log 2>>../log/orientdb.err &" - $ORIENTDB_USER
sudo -u $ORIENTDB_USER sh -c "cd \"$ORIENTDB_DIR/bin\"; /usr/bin/nohup ./shutdown.sh 1>>../log/orientdb.log 2>>../log/orientdb.err &"

Update the rc.d dirs

cd /etc/init.d
sudo update-rc.d orientdb.sh defaults

The server will now start and stop on startup/shutdown. For now we start it by hand.

sudo /etc/init.d/orientdb.sh start

Verify that it is running by opening the studio (e.g. http://localhost:2480/) or run ‘sudo /etc/init.d/orientdb.sh status’.

Now we can log in and create a new database,
Start the console:

/opt/orientdb/bin/console.sh

Create a new database:

create database remote:/yourDatabaseName yourUsername yourPassword local

Done. Grab a beer, you’ve earned it. ;)

Adding awesomeness on the run with javassist

January 17th, 2012 No comments

Creating new classes during runtime can be nice when you need it. Below is a small example of what is possible. (No interface or existing base class is used in this example so reflection is required to invoke a method)

ClassPool classPool = ClassPool.getDefault();
CtClass cc = classPool.makeClass("AwesomeNewClass");
cc.addMethod(CtMethod.make("public String getValue() { return \"Hello World!\"; }", cc));
Class awesome = cc.toClass();
Object o = awesome.newInstance();
 
Method method = awesome.getMethod("getValue");
String returnValue = (String) method.invoke(o);
Categories: Java Tags: , , , ,

Jackrabbit configuration

April 16th, 2010 No comments
1. Download the jackrabbit jca from http://jackrabbit.apache.org/downloads.html
2. Deploy it on glassfish
3. Create a new Resource Adapter Configuration (Create a new Thread-pool first if you want)
4. Create a new Connector Connection Pool with the new Resource Adapter Configuration
Add the following properties:
homeDir <full path to where your repository is located>
configFile <full path to where your repository config (repository.xml) is located>
5. Create the connector resource and name it 'jcr/repository' for example.

You can now access your repository in the code. Below is a sample.

package com.famvdploeg.jackrabbit;
 
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
 
/**
 *
 * @author wytze
 */
@Stateless
public class JackrabbitManager {
 
	@Resource(mappedName="jcr/repository", type=javax.jcr.Repository.class)
	private Repository repository;
 
	public String getFromRepo() {
		try {
			Session session = repository.login(new SimpleCredentials("username", "password".toCharArray()));
			Node root = session.getRootNode();
			Node hello = root.addNode("hello");
			hello.setProperty("message", "Hello, World!");
			session.save();
 
			// Retrieve content
            		Node node = root.getNode("hello");
            		System.out.println(node.getPath());
            		System.out.println(node.getProperty("message").getString());
 
			root.getNode("hello").remove();
 
			return "Created and removed!";
		} catch (Exception ex) {
			return ex.getMessage();
		}
	}
}

A possible Java EE 6 Servlet which you can use for WebDAV support. You will need jackrabbit-jcr-server for the base servlet. You can get it by building the source package with maven.

package com.famvdploeg.jackrabbit;
 
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.jcr.Repository;
import javax.servlet.annotation.WebServlet;
import javax.servlet.annotation.WebInitParam;
 
/**
 *
 * @author wytze
 */
@WebServlet(
	name = "webdav",
	urlPatterns = "/repository/*",
	initParams = {
		@WebInitParam(name = "resource-path-prefix", value = "/repository"),
		@WebInitParam(name = "missing-auth-mapping", value = "admin:admin"),
		@WebInitParam(name = "resource-config", value = "/WEB-INF/config.xml")
	}
)
public class SimpleWebdavServlet extends org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet {
 
	@EJB
	private RepositoryFactory repositoryFactory;
 
	private Repository repository;
 
	@PostConstruct
	public void postConstruct() {
		repository = repositoryFactory.getRepository();
	}
 
	@Override
	public Repository getRepository() {
		return repository;
	}
}

Possible extended configuration of the repository:

<!-- Store all items larger than 256 bytes in the FileDataStore -->
<DataStore class="org.apache.jackrabbit.core.data.FileDataStore">
        <param name="path" value="${rep.home}/repository/datastore"/>
        <param name="minRecordLength" value="256"/>
</DataStore>
Categories: Java Tags: , ,

Some basic Glassfish commands

April 14th, 2010 No comments

I ran out of brain capacity. So here is a list of commands to do some basic glassfish stuff.

Updating: pkg image-update
Start domain: asadmin start-domain
Stop domain: asadmin stop-domain
Deploy item: asadmin deploy <path to file>
List JNDI entries: asadmin list-jndi-entries
Categories: Java Tags: , , ,

Update-alternatives

March 12th, 2009 2 comments

Having multiple jvm’s on your linux machine can be a pain in the ass. To select which jvm to use you can use the update-alternatives command. A small example of how to add a jvm to the alternatives here:

update-alternatives --install /usr/bin/java java /usr/java/jdk1.6.0_11/bin/java 16011

This will add an entry for your jdk into the alternatives. The last number assigns the priority to this alternative. Which is the version and build number of the relase.

After adding you can use the following command to select the java version you want to use:

update-alternatives --config java

If you switch the java update-alternatives to auto it will automatically pick the java alternative with the highest priority.

Tomcat remote debugging

August 21st, 2008 No comments

I was going to write a whole lot of howto here. But why do that when you can just link to the Tomcat Wiki? ;)

The wiki that shows you how to enable remote debugging is found here.

Categories: Java Tags:

Building EJB3 applications with Maven 2

August 21st, 2008 13 comments

Here is a guide to building ejb3 applications with maven2 (from scratch). We will not be using any maven archetypes/templates but do it by hand to get a project that is as clean as possible.

First create a directory that will contain all the modules the ear file consists of. It will contain all the basic info the other projects/modules need to inherit from.

Create the pom.xml file in the directory and update it with something like the following:

<?xml version="1.0" encoding="UTF-8"?>
<project
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<modelVersion>4.0.0</modelVersion>
	<groupId>your.group.id</groupId>
	<artifactId>your-artifact-name</artifactId>
	<packaging>pom</packaging>
	<name />
	<version>0.0.1-SNAPSHOT</version>
	<description />
	<modules>
		<module>ear</module>
		<module>war</module>
		<module>ejb-jar</module>
	</modules>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.5</source>
					<target>1.5</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Then create the subdirectories ( I named them ear, war and ejb-jar in this case ) for the modules.

ejb-jar pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<parent>
		<artifactId>ejb-sample</artifactId>
		<groupId>your.group.id</groupId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>
	<groupId>your.group.id</groupId>
	<artifactId>ejb-jar</artifactId>
	<name />
	<version>0.0.1-SNAPSHOT</version>
	<packaging>ejb</packaging>
	<description />
	<dependencies>
		<dependency>
			<groupId>javax.ejb</groupId>
			<artifactId>ejb</artifactId>
			<version>3.0</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.persistence</groupId>
			<artifactId>persistence-api</artifactId>
			<version>1.0</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.testng</groupId>
			<artifactId>testng</artifactId>
			<version>5.7</version>
			<scope>test</scope>
		</dependency>			
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-ejb-plugin</artifactId>
				<configuration>
					<ejbVersion>3.0</ejbVersion>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

war pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<parent>
		<artifactId>ejb-sample</artifactId>
		<groupId>your.group.id</groupId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>
	<groupId>your.group.id</groupId>
	<artifactId>war</artifactId>
	<packaging>war</packaging>
	<name />
	<version>0.0.1-SNAPSHOT</version>
	<description />
	<dependencies>
		<dependency>
			<groupId>your.group.id</groupId>
			<artifactId>ejb-jar</artifactId>
			<type>ejb</type>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
	</dependencies>
	<build>
		<finalName>yourWarName</finalName>
	</build>
</project>

ear pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<parent>
		<artifactId>ejb-sample</artifactId>
		<groupId>your.group.id</groupId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>
	<groupId>your.group.id</groupId>
	<artifactId>ear</artifactId>
	<packaging>ear</packaging>
	<name />
	<version>0.0.1-SNAPSHOT</version>
	<description />
	<dependencies>
		<dependency>
			<groupId>your.group.id</groupId>
			<artifactId>ejb-jar</artifactId>
			<type>ejb</type>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>your.group.id</groupId>
			<artifactId>war</artifactId>
			<type>war</type>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
	</dependencies>
	<pluginRepositories>
		<pluginRepository>
			<id>codehaus snapshot repository</id>
			<url>http://snapshots.repository.codehaus.org/</url>
			<releases>
				<enabled>true</enabled>
			</releases>
		</pluginRepository>
	</pluginRepositories>
	<build>
		<finalName>your-ear-name</finalName>
		<plugins>
			<plugin>
				<artifactId>maven-ear-plugin</artifactId>
				<configuration>
					<modules>
						<ejbModule>
							<groupId>your.group.id</groupId>
							<artifactId>ejb-jar</artifactId>
						</ejbModule>
						<webModule>
							<groupId>your.group.id</groupId>
							<artifactId>war</artifactId>
						</webModule>
					</modules>
					<jboss>
             			<version>4</version>
             			<loader-repository>your.group:archive=your-ear-name.ear</loader-repository>
           			</jboss>					
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.codehaus.cargo</groupId>
				<artifactId>cargo-maven2-plugin</artifactId>
				<version>0.3-SNAPSHOT</version>
				<configuration>
					<container>
						<containerId>jboss4x</containerId>
						<type>remote</type>
					</container>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

This is basically the project structure. I hope to create a downloadable archetype of this structure so you can start with this by running the mvn archetype plugin for easy use.

BlazeDS and Hibernate proxied objects

August 13th, 2008 3 comments

In our project we are using BlazeDS in conjunction with Spring 2 and Hibernate 3. When we send Hibernate objects accross we sometimes get that proxied objects get sent as ‘ClassName$$EnhancerByCGLIB’.

This results in coercion errors on the flex end when the sent objects are being converted into the bound flex objects. To fix this I found the solution on the following page:
Adobe Forums

We use the first solution there:

package com.famvdploeg.util.blazeds;
 
import flex.messaging.io.BeanProxy;
import flex.messaging.io.PropertyProxyRegistry;
import org.hibernate.proxy.HibernateProxy;
 
/**
 * This class makes BlazeDS uses the real entity classname instead of the hibernate proxy classname,
 * this is needed so the entity can be used as a value object (RemoteClass) in flex,
 * else flex will give a type coercion error because the classname mismatches.
 *
 * See the following thread on the BlazeDS forum for more information:
 * http://www.adobe.com/cfusion/webforums/forum/messageview.cfm?forumid=72&catid=667&threadid=1335887&enterthread=y
 *
 * @author Steven De Kock
 */
public class HibernatePropertyProxy extends BeanProxy{
 
	private static final long serialVersionUID = 1612371743382649972L;
 
	/**
	 * Registers this class with BlazeDS to handle HibernateProxy instances
	 */
	public HibernatePropertyProxy() {
		super();		
		PropertyProxyRegistry.getRegistry().register(HibernateProxy.class, this);
	}
 
	/**
	 * Get actual name instead of cglib class name with $$enhancerByCglib in it.
	 */
	protected String getClassName(Object o) {
		if (o instanceof HibernateProxy) {
			HibernateProxy object = (HibernateProxy) o;
			return object.getHibernateLazyInitializer().getEntityName();
		}
		else {
			return super.getClassName(o);
		}
	}	
}

Although the referenced site states that we should be wary of any lazy initialization exceptions I don’t think that is a problem. This is because the serialization process is taking place behind an opened Hibernate session in our current setup and the proxied objects are still attached to the session. So using this fix works for us.

Oh yeah, don’t forget to load the bean from your spring context. ;)
Put in the following line of xml in your spring context xml.

    <!-- Initialize the hibernatePropertyProxy handler so flex gets actual class name instead of $$enhancerbycglib -->    
	<bean id="hibernatePropertyProxy" class="com.famvdploeg.util.blazeds.HibernatePropertyProxy"/>

Generating sql database schema with maven2 for hibernate3

July 31st, 2008 3 comments

I’m using maven with hibernate3 plugin to generate the sql code for my database schema/tables. I do so with the following configuration.
Also make sure you declare your driver in the plugin dependencies to be sure the driver can be loaded in the plugin. Otherwise you might get some JDBC exceptions.

Command line example:
mvn clean compile hibernate3:hbm2ddl
			<!-- 
				Hibernate 3 Plugin, used for schema creation
				Usage example: mvn clean compile hibernate3:hbm2ddl
			 -->
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>hibernate3-maven-plugin</artifactId>
				<version>2.0-alpha-2</version>
				<configuration>
					<components>
						<component>
							<name>hbm2ddl</name>
							<implementation>annotationconfiguration</implementation>																									
						</component>							
					</components>
					<componentProperties>		
						<!-- Create Drop Statements -->					
						<drop>false</drop>
						<!-- Enable Annotations -->
						<jdk5>true</jdk5>
						<!-- Define Database Properties to Use -->
						<propertyfile>target/classes/database.properties</propertyfile>
						<!-- Pretty Format SQL Code -->
						<format>true</format>
						<!-- Create tables automatically? -->
						<export>false</export>
						<!-- Output filename -->
						<outputfilename>schema.sql</outputfilename>
					</componentProperties>
				</configuration>						
				<dependencies>
					<dependency>
						<groupId>com.oracle</groupId>
						<artifactId>ojdbc14</artifactId>
						<version>${oracle-driver.version}</version>
					</dependency>
				</dependencies>