Posts Tagged JPA

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.

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)

Pro EJB 3 – Java Persistence API for $10

Same rules as before, you can get this e-book from Apress’ daily deal site for $10 within the 24-hour period.

1590596455 Pro EJB 3

This is one of the few books recommended for SCBCD 5.0 exam.

Comments (1)

EJB Injection in JSF Managed Beans

While trying to create a simple prototype for an application which uses JSF, EJB 3 and JPA, I decided to implement the suggestions from the article: Using an EJB Session Bean as a Model Facade.

I was particularly interested in injecting my EJBs to my JSF Managed Beans (the article mentioned that it should be possible to do this kind of injection with JSF Managed Beans and Servlets).

public class CatalogServlet extends HttpServlet {

@EJB private CatalogFacade cf;

// some variables and methods
}

I tried using JBoss 4 since it already had lots of available documentation regarding EJB 3 only to find out that this feature is not yet supported.

I tried switching to JBoss 5 Beta 4 but the error was the same.

16:16:31,765 ERROR [JBossInjectionProvider] Injection failed on managed bean.
javax.naming.NameNotFoundException: “Name of your Managed Bean goes here” not bound

Hmm, I should probably try this with GlassFish one of these days.

Recommended books:

0131738860 1933988347 1847192602

Comments (3)