Posts Tagged TopLink

TopLink JPA and HSQLDB Quirk

I discovered a weird issue when using HSQLDB as database provider for TopLink JPA.

We need to explicitly include the toplink.target-database property in the persistence.xml file to make it work.

<property name="toplink.target-database" value="HSQL"/>

Without that, you are most likely to get this error below when you run your application:


Query: DataModifyQuery()
	at oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:304)
       ...
Caused by: java.sql.SQLException: Table not found in statement

I did not have that property set when I was using TopLink JPA with MySQL so I was a bit surprised why it was not working initially when I switched to HSQLDB.

Anyway, here’s the complete properties element of persistence.xml for HSQLDB for your reference:

      <properties>
         <property name="toplink.ddl-generation" value="drop-and-create-tables" />
         <property name="toplink.jdbc.driver" value="org.hsqldb.jdbcDriver" />
         <property name="toplink.jdbc.url" value="jdbc:hsqldb:notifications" />
         <property name="toplink.jdbc.user" value="sa" />
         <property name="toplink.jdbc.password" value="" />
         <property name="toplink.target-database" value="HSQL"/>
      </properties>

Hope I can save you guys a lot of trouble through this post.

Because it certainly took me hours to figure this thing out.

Advertisements

Comments (6)

Flex, BlazeDS and JPA

After several days of playing with Flex, I’ve managed to create a simple Java-based backend using BlazeDS and the Java Persistence API (JPA).

In this post, we will try to implement what used to be a very popular application (during the early days of the Internet), the “Guest Book“.

What you’ll need:

The assumption here is that you are already comfortable with Java and databases, and you just want to know how to make your Flex application communicate to your Java backend.

We now proceed to creating our form Using Flex Builder.

guestbook.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="absolute" xmlns:local="*">
 <mx:Form x="10" y="10" width="270" height="150">
 	<mx:FormItem label="Name">
 		<mx:TextInput id="guestname" />
 	</mx:FormItem>
 	<mx:FormItem label="Message">
 		<mx:TextArea id="guestmessage" />
 	</mx:FormItem>
 	<mx:FormItem label="">
 		<mx:Button label="Submit" />
 	</mx:FormItem>
 </mx:Form>
</mx:Application>

Switching to “Design” view should show us the form that we just created.

Look how nice and easy it was to create the form.

But wait, this application doesn’t do anything yet, so let’s move on to adding some logic.

Let’s try to modify the submit button to call our remote object:

<mx:Button label="Submit"
    click="guestBookService.add(guestBookEntry)"/>

Adding this line alone will cause a compile error because we haven’t told Flex what the guestBookService and guestBookEntry objects are all about.

First we need to create an ActionScript class named GuestBookEntry.as which will correspond to our remote JPA entity named GuestBookEntry.java (located under the guestbook package).

package
{
    [Bindable]
    [RemoteClass(alias="guestbook.GuestBookEntry")]
    public class GuestBookEntry
    {
        public function GuestBookEntry()
        {
        }

        private var _guestName:String;
        private var _guestMessage:String;

        public function get guestName():String {
            return _guestName;
        }

        public function set guestName(guestName:String):void {
            _guestName=guestName;
        }

        public function get guestMessage():String {
            return _guestMessage;
        }

        public function set guestMessage(guestMessage:String):void {
            _guestMessage=guestMessage;
        }
    }
}

Notice how the constructor, setters and getters are different from how you would normally do it in Java.

We now update guestbook.mxml to include a reference to our guestBookEntry object (also called a custom component). This should be added as a child of the Application element.

<local:GuestBookEntry id="guestBookEntry"
    guestName="{guestname.text}"
    guestMessage="{guestmessage.text}" />

The curly braces mean that any changes to the text values of the form elements in guestbook.mxml would be directly applied to the guestBookEntry instance.

That should leave us with one more compile error to deal with, which is that of the missing reference to guestBookService.

Just add the fragment below as a child to Application and we’re all done! At least with the Flex part.

<mx:RemoteObject id="guestBookService"
    destination="guestBookService"
    source="guestbook.GuestBookService"
    channelSet="{cset}"/>
<mx:ChannelSet id="cset">
    <mx:channels>
        <mx:AMFChannel id="myamf"
            uri="http://localhost:8400/guestbook/messagebroker/amf"/>
    </mx:channels>
</mx:ChannelSet>

I’m sorry if I cannot explain the ChannelSet details as of now, because I’m as clueless as you are. We just need to make sure that they match the values in our BlazeDs backend and we’re good to go.

From your turnkey download, locate a file named blazeds.war, if you’ve done some Struts programming before, this is the same as the struts-blank.war which can serve as a template for new projects.

Import this war as a project in Eclipse WTP, and name this project guestbook (remember that our backend needs to match the entries we added for the RemoteObject and ChannelSet).

When you’re done setting up the project in Eclipse, navigate to “WEB-INF\flex\”. At this point we are only interested in “remoting-config.xml” where we should be defining a reference to our remote object.

Add these lines in between the adapters and default-channels:

   <destination id="guestBookService">
<properties>
         <source>guestbook.GuestBookService</source>
      </properties>
   </destination>

To setup JPA, we need to create a folder named META-INF under src and create a file named persistence.xml. Also, make sure to add TopLink JPA jars and your JDBC driver to WEB-INF\lib.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
 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">
<persistence-unit name="guestbook" transaction-type="RESOURCE_LOCAL">
<provider>
           oracle.toplink.essentials.PersistenceProvider
        </provider>
        <class>guestbook.GuestBookEntry</class>
<properties>
<property name="toplink.ddl-generation" value="drop-and-create-tables"/>
<property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="toplink.jdbc.url" value="jdbc:mysql://localhost:3306/guestbook"/>
<property name="toplink.jdbc.password" value="guestbook"/>
<property name="toplink.jdbc.user" value="guestbook"/>
 	</properties>
 </persistence-unit>
</persistence>

We now create the Java objects GuestBookService and GuestBookEntry:

@Entity
public class GuestBookEntry {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private long id;

    private String guestName;
    private String guestMessage;

    public GuestBookEntry() {}

    // getters and setters
}
public class GuestBookService {

    private EntityManagerFactory emf = null;

    public EntityManagerFactory getEMF() {
        if (emf == null) {
            emf = Persistence.createEntityManagerFactory("guestbook");
        }
        return emf;
    }

    public void add(GuestBookEntry guestBookEntry) {
        EntityManager em = getEMF().createEntityManager();
        try {
            em.getTransaction().begin();
            em.persist(guestBookEntry);
            em.getTransaction().commit();
        } catch (Exception e) {
            em.getTransaction().rollback();
            e.printStackTrace();
        } finally {
            em.close();
        }
    }

}

The guestbook.war can be downloaded from this location. The file uses an odt extension because of hosting limitations. Please rename to .war accordingly.

Also, JAR files from BlazeDS, TopLink and MySQL driver were not included in the distribution.

Let me know if you encounter any problems while running the application.

Recommended books:

1933988746 1933988347

Comments (11)