nedeľa 26. júla 2009

How to configure PostgreSQL datasource in Embedded JBoss

I have spent more than hour fighting this issue. I will wrote it down rather than forgetting about it. So that in case I have to do this again I will know where to look, and I hope that it might be helpful for others as well.

Environment: Seam 2.1.2, PostgreSQL, JBoss embedded

Scenario: Project generated by seam-gen originally used Hypersonic SQL database (HSQLDB). Later Postgre SQL database (PGSQL) was installed and properly configured with dev build profile. However tests which are running in embedded JBoss still use HSQLDB, the goal is to configure tests to run on PGSQL as well.

Documentation says: By default, a generated project will use the java:/DefaultDS (a built in HSQL datasource in Embedded JBoss) for testing. If you want to use another datasource place the foo-ds.xml into bootstrap/deploy directory.

Sounds easy considering that dev profile is already configured with PGSQL datasource which is woking with ordinary JBoss 5.1.0. One would assume that it is sufficient to copy myproject-dev-ds.xml file to bootstrap/deploy directory (rename it to myproject-test-ds.xml for clarity sake), then change persistence-test.xml according to persistence-dev.xml and all should work.

But in case this is done, running ant test task produces only this incomprehensible error:
org.jboss.deployers.client.spi.IncompleteDeploymentException: Summary of incomplete deployments (SEE PREVIOUS ERRORS FOR DETAILS):
*** CONTEXTS MISSING DEPENDENCIES: Name -> Dependency{Required State:Actual State}
jboss.jca:name=myProjectDatasource,service=DataSourceBinding
-> jboss:service=invoker,type=jrmp{Start:** NOT FOUND **}
-> jboss:service=invoker,type=jrmp{Create:** NOT FOUND **}
*** CONTEXTS IN ERROR: Name -> Error
jboss:service=invoker,type=jrmp -> ** NOT FOUND **
at org.jboss.deployers.plugins.deployers.DeployersImpl.checkComplete(DeployersImpl.java:576)
at org.jboss.deployers.plugins.main.MainDeployerImpl.checkComplete(MainDeployerImpl.java:559)
at org.jboss.embedded.Bootstrap.bootstrapURL(Bootstrap.java:149)
at org.jboss.embedded.Bootstrap.bootstrap(Bootstrap.java:183)
at org.jboss.embedded.Bootstrap.bootstrap(Bootstrap.java:195)
at org.jboss.seam.mock.EmbeddedBootstrap.startAndDeployResources(EmbeddedBootstrap.java:11)
at org.jboss.seam.mock.AbstractSeamTest.startJbossEmbeddedIfNecessary(AbstractSeamTest.java:1024)
at org.jboss.seam.mock.AbstractSeamTest.startSeam(AbstractSeamTest.java:915)
at org.jboss.seam.mock.SeamTest.startSeam(SeamTest.java:58)
... Removed 15 stack frames
where myproject-test-ds.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
  <jndi-name>myProjectDatasource</jndi-name>

  <use-java-context>false</use-java-context><!-- note this line -->

  <connection-url>jdbc:postgresql://localhost:5432/test</connection-url>
  <driver-class>org.postgresql.Driver</driver-class>
  <user-name>test</user-name>
  <password>test</password>
</local-tx-datasource>
</datasources>
and persistence-test.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Persistence deployment descriptor for test profile -->
<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_1_0.xsd"
       version="1.0">
<persistence-unit name="myProject">
  <provider>org.hibernate.ejb.HibernatePersistence</provider>

  <jta-data-source>myProjectDatasource</jta-data-source><!-- note this line -->

  <properties>
      <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
      <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      <property name="hibernate.show_sql" value="true"/>
      <property name="hibernate.format_sql" value="true"/>
      <property name="jboss.entity.manager.factory.jndi.name" value="java:/myProjectEntityManagerFactory"/>
  </properties>
</persistence-unit>
</persistence>
So both files seem to be configured properly, how come it is not working then? Solution can be found here: https://jira.jboss.org/jira/browse/JBPAPP-2223.

Workaround Description: remove "false" from the datasource file and add "java:/" prefix to the content of jta-data-source element in persistence.xml

And indeed after changing myproject-test-ds.xml like this:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
 <local-tx-datasource>
     <jndi-name>myProjectDatasource</jndi-name>
     <connection-url>jdbc:postgresql://localhost:5432/test</connection-url>
     <driver-class>org.postgresql.Driver</driver-class>
     <user-name>test</user-name>
     <password>test</password>
 </local-tx-datasource>
</datasources>
and persistence-test.xml like this:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Persistence deployment descriptor for test profile -->
<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_1_0.xsd"
          version="1.0">
 <persistence-unit name="myProject">
     <provider>org.hibernate.ejb.HibernatePersistence</provider>

     <jta-data-source>java:/myProjectDatasource</jta-data-source><!-- note this line -->

     <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
         <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
         <property name="hibernate.show_sql" value="true"/>
         <property name="hibernate.format_sql" value="true"/>
         <property name="jboss.entity.manager.factory.jndi.name" value="java:/myProjectEntityManagerFactory"/>
     </properties>
 </persistence-unit>
</persistence>
everything works like a charm.