0

Please help, this is driving me crazy. I've been researching this for hours, and couldn't find an example that matches my situation.

I'm writing a very simple Java EE App which authenticates users from a standalone client. In Netbeans 7.3, I have a Java EE application project with an EJB module, an application client project, and a separate java class library for the bean's remote interface and the entities.

The EJB module has one bean (AccountsBean.java), the class library project has the bean's remote interface (AccountsBeanRemote.java), the entity (Account.java) and the persistence.xml file. Here's a picture of the project layout so you can see it clearly: http://snag.gy/EoyQa.jpg

I want to pass Account instances to the client.

I'm using Glassfish 3.1 and Java DB (Derby).

I have 3 databases: AccountsTest (which I want to use here), sample, and sun-appserv-samples (these two are created during the Glassfish install).

The problem is that is doesn't matter what database connection I specify in persistence.xml, the table always gets created in the sample database sun-appserv-samples. It seems to me that the bean ignores the persistence.xml file. Maybe the problem is that persistence.xml is in a separate project from the bean, but this is the only way the IDE lets me do it if I want to pass Account instances to the remote client.

Here's my persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
  <persistence-unit name="LoginTest-libPU" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>logintest.lib.Account</class>
    <properties>
      <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/AccountsTest"/>
      <property name="javax.persistence.jdbc.password" value="app"/>
      <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
      <property name="javax.persistence.jdbc.user" value="app"/>
      <property name="eclipselink.ddl-generation" value="create-tables"/>
    </properties>
  </persistence-unit>
</persistence>

And AccountsBean.java:

@Stateless
public class AccountsBean implements AccountsBeanRemote {

    @PersistenceContext(unitName = "LoginTest-libPU")
    EntityManager em;

    @Override
    public Account create(String name, String password) {
        ...
    }

    @Override
    public void remove(int id) {
        ...
    }

    @Override
    public boolean checkPassword(int id, String password) {
        ...
    }
}

Account.java:

@Entity
@Table(name = "ACCOUNTS")
public class Account implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    private String password;

    public Account() {
    }

    ...other methods

I guess I didn't configure the EntityManager correctly, but where should I put persistence.xml? If I put it in the EJB module, I also have to put the entities in the EJB module, and they will be inaccessible to the client.

Thanks in advance!

1 Answers1

0

Let me start by stating that it's not clear to me exactly why you're seeing such behavior because I'm not familiar with the expected behavior given what you're doing in the Glassfish/Java EE runtime: you're setting up a direct connection. Instead, in a Java EE environment you want "container managed persistence units" [here's a guess: the container is defaulting jta-data-source to 'sun-appserv-samples'].

So, let Java EE manage the connection for you:

  1. In Glassfish, define a JDBC Connection Pool with id "TestAccountPool". You can do this from the admin panel, or via command line. This specifies your datasourceclassname (look here for Derby), transaction isolation levels, and config properties such as:

    networkProtocol=jdbc\\:derby
    serverName=localhost
    port=1527  [OR portNumber=1527; I use port, some docs say portNumber]
    databaseName=AccountsTest
    user=app
    password=app
    
  2. Define a JDBC Resource with JNDI name "jdbc/TestAccountData" that references the "TestAccountPool".

  3. Adapt your persistence.xml file to refer to the managed database connection using the JNDI name:

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.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_2_0.xsd">
    
      <persistence-unit name="LoginTest-libPU" transaction-type="JTA">
    
        <jta-data-source>jdbc/TestAccountData</jta-data-source>
    
        <class>logintest.lib.Account</class>
    
        <properties>
          <property name="eclipselink.ddl-generation" value="create-tables"/>
        </properties>
      </persistence-unit>
    </persistence>
    

Supporting Java SE Clients

If you'd also like to use your entities in a Java SE then:

  1. add your originally defined <persistence-unit> ... </persistence-unit> into the persistence.xml file.

  2. Change the name of this second persistence-unit; it must be unique. My tooling (eclipse w/ glassfish plugin) complains about multiple persistence units; I ignore such warnings.

  3. Change the transaction type from "JTA" to "RESOURCE_LOCAL", or just remove it: in a Java EE container the transaction type defaults to JTA (per spec), and in Java SE it defaults to RESOURCE_LOCAL.

  4. Use the new name to the new persistence-unit in the Java SE code.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Richard Sitze
  • 8,262
  • 3
  • 36
  • 48
  • Oh, this makes sense. The persistence.xml was generated by netbeans, and because it was in a separate class library, it considered it as a Java SE environment. So it set up a direct connection instead of using the container. But I still can't get it working. Now I get this error when I call persist(): `java.lang.IllegalArgumentException: Object: logintest.ejb.Account[ id=0 ] is not a known entity type` So where should I put persistence.xml? 1. in the class library? 2. in the ejb module? 3. in the ejb module, and in the class library with a different persistence unit name? – icecreamfields Mar 10 '13 at 13:22