cancel
Showing results for 
Search instead for 
Did you mean: 

JPA with MySQL-Data-Source

Former Member
0 Kudos

Hello Forum,

I have a question regarding usage of a MySQL-Data-Source in combination with JPA

on the SAP NetWeaver Application Server, Java ™ EE 5 Edition.

I have setup a custom datasource like explained in paper:

"Working with Database Tables, DataSources and JMS Resources"

- registered the database driver via telnet (Using mysql-connector-java-5.0.3-bin.jar)

- created the data-sources.xml file underneath the META-INF dir of the EAR project

[code]

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE data-sources SYSTEM "data-sources.dtd" >

<data-sources>

<data-source>

<data-source-name>titan_cruises_ds</data-source-name>

<driver-name>mysql-connector-java-5.0.3-bin.jar</driver-name>

<init-connections>1</init-connections>

<max-connections>10</max-connections>

<max-time-to-wait-connection>60</max-time-to-wait-connection>

<expiration-control>

<connection-lifetime>600</connection-lifetime>

<run-cleanup-thread>60</run-cleanup-thread>

</expiration-control>

<sql-engine>native_sql</sql-engine>

<jdbc-1.x>

<driver-class-name>com.mysql.jdbc.Driver</driver-class-name>

<url>jdbc:mysql://ourHost.internal.com:3306/practise_titan_cruises</url>

<user-name>myUser</user-name>

<password>myPass</password>

</jdbc-1.x>

</data-source>

</data-sources>

[/code]

After that I manually created the persistence.xml underneath the META-INF dir of the EJB project.

[code]

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">

<persistence-unit name="titan_cruises_pu">

<jta-data-source>titan_cruises_ds</jta-data-source>

</persistence-unit>

</persistence>

[/code]

After that I created the Entity named "Cabin" and the corresponding table within the db.

Entity code:

[code]

package de.collogia.beans.pojo.ship;

import java.io.IOException;

import java.io.Serializable;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.Table;

/**

  • This persisted POJO class models the cabin data.

  • <p>

  • In this class persistence annotations are placed on the getter methods

  • of the attributes. This tells the persistence manager to access them

  • via the corresponding get- and set-Methods.</p>

  • (Unfortunately this does not work on NetWeaver and I had to place them

  • on field level aggain...)

*

  • @author Henning Malzahn (malzahn@edvbm.de)

*

  • svn-revision: $Rev:: 670 $:

  • svn-lasted-edited-by: $Author:: henning $:

  • svn-last-changed: $Date:: 2007-02-21 21:49:51 +0100 (Wed, 21 Feb 2007) $:

*/

@Entity

@Table(name = "cabin")

public class Cabin implements Serializable {

/** The generated serial version UID used for serialization. */

private static final long serialVersionUID = -8522497314498903378L;

/** The actual version number of this class used for serialization. */

private static int actualVersion = 1;

/** The cabin's id. */

@Id

@GeneratedValue

@Column(name = "id")

private long id;

/** The cabin's name */

@Column(name = "name")

private String name;

/** The cabin's deck level */

@Column(name = "deck_level")

private int deckLevel;

/** The cabin's ship id */

@Column(name = "ship_id")

private int shipId;

/** The cabin's bed count */

@Column(name="bed_count")

private int bedCount;

/----


Serialization/ Deserialization methods -
/

/**

  • Method that is responsible for deserialization of the object.

  • @param in The <code>ObjectInputStream</code> object to read

  • the data from.

  • @throws IOException That may occur when reading from the

  • <code>ObjectInputStream</code> object

  • @throws ClassNotFoundException That may occur when invoking the default

  • deserialization mechanism.

*/

private void readObject(final java.io.ObjectInputStream in)

throws IOException, ClassNotFoundException {

/* Invoke default deserialization mechanism. */

in.defaultReadObject();

/* Read the actual version number of the class. */

actualVersion = in.readInt();

} // End of readObject()

/----


/

/**

  • Method that is responsible for serialization of the object.

  • @param out The <code>ObjectOutputStream</code> object to write

  • the data to.

  • @throws IOException That may occur when writing to the

  • <code>ObjectOutputStream</code> object.

*/

private void writeObject(final java.io.ObjectOutputStream out)

throws IOException {

/* Invoke default serialization mechanism. */

out.defaultWriteObject();

/* Write the actual version number of the class. */

out.writeInt(actualVersion);

} // End of writeObject()

/----


Defining constructors -
/

/**

  • Private default constructor.

*/

private Cabin() {

} // End of default constructor

/----


/

/**

  • Full constructor.

  • @param name The cabin's name.

  • @param deckLevel The cabin's deck level.

  • @param shipId The cabin's ship id.

  • @param bedCount The cabin's bed count.

*/

public Cabin(final String name,

final int deckLevel,

final int shipId,

final int bedCount) {

this.name = name;

this.deckLevel = deckLevel;

this.shipId = shipId;

this.bedCount = bedCount;

} // End of full constructor

/----


Overridden class methods -
/

/**

  • Returns a string representation of the cabin's data.

  • @see java.lang.Object#toString()

*/

@Override

public String toString() {

StringBuffer strBuf = new StringBuffer();

strBuf.append(this.name);

strBuf.append("\n");

strBuf.append(this.deckLevel);

strBuf.append("\n");

strBuf.append(this.shipId);

strBuf.append("\n");

strBuf.append(this.bedCount);

return strBuf.toString();

} // End of toString()

/----


Defining instance methods -
/

/**

  • Get method for the member "<code>id</code>".

  • @return Returns the id.

*/

public long getId() {

return this.id;

}

/**

  • Set method for the member "<code>id</code>".

*

  • HTDODO hm: Check whether it is possible to have setId method

  • using private accesss level with NetWeaver JPA-Provider!

  • @param id The id to set.

*/

private void setId(final long id) {

this.id = id;

}

/----


/

/**

  • Get method for the member "<code>name</code>".

  • @return Returns the name.

*/

public String getName() {

return this.name;

}

/**

  • Set method for the member "<code>name</code>".

  • @param name The name to set.

*/

public void setName(final String name) {

this.name = name;

}

/----


/

/**

  • Get method for the member "<code>deckLevel</code>".

  • @return Returns the deckLevel.

*/

public int getDeckLevel() {

return this.deckLevel;

}

/**

  • Set method for the member "<code>deckLevel</code>".

  • @param deckLevel The deckLevel to set.

*/

public void setDeckLevel(final int deckLevel) {

this.deckLevel = deckLevel;

}

/----


/

/**

  • Get method for the member "<code>shipId</code>".

  • @return Returns the shipId.

*/

public int getShipId() {

return this.shipId;

}

/**

  • Set method for the member "<code>shipId</code>".

  • @param shipId The shipId to set.

*/

public void setShipId(final int shipId) {

this.shipId = shipId;

}

/----


/

/**

  • Get method for the member "<code>bedCount</code>".

  • @return Returns the bedCount.

*/

public int getBedCount() {

return this.bedCount;

}

/**

  • Set method for the member "<code>bedCount</code>".

  • @param bedCount The bedCount to set.

*/

public void setBedCount(final int bedCount) {

this.bedCount = bedCount;

}

/----


/

} // End of class Cabin

[/code]

After that I created the TravelAgentBean, a Stateless Session Bean, implementing

a remote interface that allows construction and persisting of new Cabin objects:

[code]

package de.collogia.beans.session.stateless;

import javax.ejb.Stateless;

import javax.persistence.EntityManager;

import javax.persistence.PersistenceContext;

import de.collogia.beans.pojo.ship.Cabin;

/**

  • Class that implements the <code>TravelAgentRemote</code> interface

  • and defines the business methods of the TravelAgent service.

  • @author Henning Malzahn (malzahn@edvbm.de)

*

  • svn-revision: $Rev:: 670 $:

  • svn-lasted-edited-by: $Author:: henning $:

  • svn-last-changed: $Date:: 2007-02-21 21:49:51 +0100 (Wed, 21 Feb 2007) $:

*/

@Stateless

public class TravelAgentBean implements TravelAgentRemote {

/** The <code>Log</code> object for this class. */

// private static final Log LOGGER;

/** The <code>PersistenceManager</code> object. */

@PersistenceContext(unitName = "titan_cruises_pu")

EntityManager em;

/----


Static initializer -
/

// static {

// LOGGER = LogFactory.getLog(TravelAgentBean.class);

// } // End of static initializer block

/----


Implementing remote interface methods -
/

/**

  • {@inheritDoc}

*/

public void createCabin(final Cabin cabin) {

this.em.persist(cabin);

} // End of createCabin()

/----


/

} // End of class TravelAgentBean

[/code]

After that I created a Controller class containing a main method that looks up the remote

interface of the TravelAgentBena like explained in document "Accessing Enterprise JavaBeans Using JNDI

in SAP NetWeaver Application Server, Java ™ EE 5 Edition" written by Validimir Pavlov of SAP NetWeaver

development team.

Unfortunately I receive an Exception after invoking the createCabin(...) method.

On the console of the NWDS I receive:

[code]

javax.ejb.EJBException: Exception in getMethodReady() for stateless bean sap.com/test2Earannotation|test2Ejb.jarannotation|TravelAgentBean;

nested exception is: com.sap.engine.services.ejb3.util.pool.PoolException: javax.ejb.EJBException: Cannot perform injection over bean instance

....

Caused by: java.lang.RuntimeException: The persistence unit is inconsistent:

The entity >>de.collogia.beans.pojo.ship.Cabin<< is mapped to the table >>cabin<<, which does not exist.

[/code]

But if I look at the log file located in "C:\NWAS_JAVAEE5\JP1\JC00\j2ee\cluster\server0\log\defaultTrace.0.trc"

I see the real reason is:

[code]

[EXCEPTION]

#6#1064#42000#You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax

to use near '"cabin"' at line 1#collnx02.collogia.de:3306:null:practise_titan_cruises#select * from "cabin"#com.mysql.jdbc.exceptions.MySQLSyntaxErrorException:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"cabin"' at line 1

at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:936)

at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2870)

at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)

at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)

at com.mysql.jdbc.Connection.execSQL(Connection.java:3124)

at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1149)

at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1262)

at com.sap.sql.jdbc.basic.BasicPreparedStatement.executeQuery(BasicPreparedStatement.java:99)

at com.sap.sql.jdbc.direct.DirectPreparedStatement.executeQuery(DirectPreparedStatement.java:307)

at com.sap.sql.jdbc.direct.DirectPreparedStatement.executeQuery(DirectPreparedStatement.java:264)

at com.sap.engine.services.dbpool.wrappers.PreparedStatementWrapper.executeQuery(PreparedStatementWrapper.java:274)

[/code]

My goodness - what a long post - sorry for this - I hope I provided all information

necessary to deal with the issue.

Am I thinking in the right direction to blame attribute [code]<sql-engine>native_sql</sql-engine>[/code]

of file data-sources.xml for the beaviour? Are there any other argument options than native_sql?

Thanks in Advance!

Henning Malzahn

Accepted Solutions (1)

Accepted Solutions (1)

adrian_goerler
Employee
Employee
0 Kudos

Hi Henning,

defining the data source for <i>native sql</i> is OK.

I suggest to investigate in a different direction:

SAP JPA respects the case of table and column names. You have explicitly specified the name of the table "cabin" in lower case:

@Entity

@Table(name = "cabin")

public class Cabin ...

SAP JPA now validates that a table named "cabin" exists with the table name being lower case. This check fails. Please double check that you have created the table in lower case. Or change the @Table and @Column annotations so that they match the case of your table definition.

Best regards,

Adrian

Former Member
0 Kudos

Hello Adrian,

the table name is lower case. We are developing an application which is targeting

NetWeaver and JBoss application server which is using Hibernate as JPA-Persistence provider. Therefore I'am able to use the property hibernate.hbm2ddl.auto in the persistence.xml of the JBoss project to automatically generate the tables on the MySQL-Server instance. I double checked that the cabin table is lower case using

the phpMyAdmin tool and the mysql command line client on the server itself.

Henning

Former Member
0 Kudos

Hello Forum,

another day, another attempt to solve the problem

The Exception logged in file "C:\NWAS_JAVAEE5\JP1\JC00\j2ee\cluster\server0\log\defaultTrace.0.trc" contains

select * from "cabin"

as the generated SQL statement.

Issuing that statement using the mysql command line client yields the same error:

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual...

Is that really the raw generated SQL statement of the NetWeaver JPA implementation?

Issuing the same statement withoutd the quotes yields in:

ERROR 1046 (3D000): No database selected.

The statement that works using the mysql command line client is:

select * from practise_titan_cruises.cabin;

So it looks like MySql needs the name of the db configured within the data-sources.xml

file. Is there an option to increase logging messages related to JPA on the NetWeaver?

Any further ideas are greatly appreciated...

Henning Malzahn

PS: If you do not care about using MySQL as datasource please tell me - I can imagine

that SAP's main focus is related to their own db. If so we have to think about using the

db shipped with NetWeaver...

adrian_goerler
Employee
Employee
0 Kudos

Hi Hennig,

we are aware of the popularity of MySQL and taking it very seriuosly. Although MySQL is not supported as a database for the system schema of NetWeaver, we are testing SAP JPA regularily with MySQL. MySQL should be usable by SAP JPA as an "external" database.

I think what is wrong here is the following:

By Default, MySQL is quoting delimited identifiers by back ticks (`). SAP JPA, however generates delimited identifiers enclose in double quotes ("). You can advise MySQL to accept double quotes using the "sql mode" ANSI_QUOTES as described <a href="http://dev.mysql.com/doc/refman/4.1/en/identifiers.html">here</a>.

I hope this helps.

Best regards,

Adrian

Former Member
0 Kudos

Hello Adrian,

I will try your tipp and post the result.

But another idea came to my mind:

What about switching to Hibernate as persistence provider?

Are the issues mentioned in the following thread solved now?

The file version.asc (located underneath the folder where I've extracted the installation

files of NetWeaver) contains the following information:

2006/09/27 50081053

Best regards,

Henning Malzahn

Former Member
0 Kudos

Hello Adrian,

perfect - that was the trick.

Issuing

SET sql_mode='ANSI_QUOTES';

using mysql command line

client did not work, so i modified the server's start up script

/etc/init.d/mysql

and inserted the option

--sql-mode=ANSI

to the regular startup options of the daemon. After restarting the server I received an

Exception due to missing table TMP_SEQUENCE, after creating the table

like mentioned in this thread:

everything worked and I can insert new entities!

Thank you!

Best regards,

Henning

PS: Shall I open another thread for the question related to switching to

hibernate as JPA provider?

adrian_goerler
Employee
Employee
0 Kudos

Hi Henning,

good to know that this solved your issue.

Of course you are free to open a thread with respect to using Hibernate Entity Manager as a JPA provider. However, I can tell you so much right away:

- Using Hibernate Entity Manager as a JPA provider is not possible with the version of SAP NetWeaver Java EE 5 Edition you are using. The issue has been fixed in the upcoming production version of NetWeaver Java EE 5. But the fix is unfortunately not-yet publicly available.

- Using plain Hibernate is possible

- Please use SAP JPA for the time beeing. You are very welcome to share your thoughts on SAP JPA here

Best regards,

Adrian

Former Member
0 Kudos

Hello Adrian,

ok - Thanks for the answer - then I have to wait until the next release or the fix is

available.

To be honest I'am really impressed by the new EJB 3.0 standard and thanks to JPA

(no code changes necesssary) it's ok for me to rely on SAP JPA.

Despite the fact it's working now I have to do some changes to my code currently

developed using JBoss/ Hibernate combination. Hibernate allows you to have the

default no-arg constructor with private visibility - any special reason for the fact that

only protected is allowed on NetWeaver? The entities in the project are final classes

so declaring a ctor protected doesn't really make sense...

Another thing is the extra TMP_SEQUENCE table wich isn't necessary using JBoss and

Hibernate - what's the reson for that?

Also the persistence.xml parameter

hibernate.hbm2ddl.auto

with the value of create-drop is very useful while

developing the app - everytime you deploy the project you get a fresh database.

Is there a comparable option for NetWeaver?

Best regards,

Henning Malzahn

adrian_goerler
Employee
Employee
0 Kudos

Hi Henning,

> Despite the fact it's working now I have to do some

> changes to my code currently

> developed using JBoss/ Hibernate combination.

> Hibernate allows you to have the

> default no-arg constructor with private visibility -

> any special reason for the fact that

> only protected is allowed on NetWeaver?

Here we strictly implemented the checks according to the requirements of the JPA specification. Technically, we could do with private constructors as well. But the JPA specifications requires the constructor to be protected to allow a JPA implementation to subclass entities if needed.

> The entities in the project are final classes

> so declaring a ctor protected doesn't really make

> sense...

For the same reason, your entities should not be final. Are we missing a check here ?

> Also the persistence.xml parameter

>

hibernate.hbm2ddl.auto

with the value of

> create-drop is very useful while

> developing the app - everytime you deploy the project

> you get a fresh database.

> Is there a comparable option for NetWeaver?

No, unfortunately, there is no comparable option in SAP JPA (yet). We understand that there is a need for forward mapping. We would have liked to delegate this task to the JPA design time (i.e. Dali). However, we had to discover that Dali does not perform this task properly and we can't recommend using it any more.

Consequently, there is no automatic schema generation in SAP JPA 1.0.

>

> Another thing is the extra TMP_SEQUENCE table which

> isn't necessary using JBoss and

> Hibernate - what's the reason for that?

With Hibernate Entity Manager, the id generation strategy in use with GenerationType.AUTO depends on the database dialect. This means that depending on the database dialect, IDENTITY columns, SEQUENCES or generator tables (TableHiLo) are required. As Hibernate has the before mentioned schema generation property this fact can be hidden to the user.

In SAP JPA, we are always using a table generator if GenerationType.AUTO is used. This allows for better portability across databases. It requires the table TMP_SEQUENCE. As we unfortunately do not have a schema generation capability, the user must create this table.

Best regards,

Adrian

Former Member
0 Kudos

Hello Adrian,

thank you for the detailed response! As I'am currently writing my diploma work as final

exam for my computer science studies the information provided is very useful to me.

The sub-title of the work is "A comparsion implementation using JBoss and

SAP NetWeaver."

Despite the fact I read JBoss is the EJB 3.0 reference implementation (a wrong

information?) I now see that the folks over there are not following the rules very strictly

> For the same reason, your entities should not be final. Are we missing a check here ?

I haven't deployed the real project to SAP NetWeaver as I'am discovering the basics in the moment but I think I have to change a bite more to be standard compliant.

I double checked a minute ago - and yes - my entities are final and have private

default ctors. Despite that fact they were successfully deployed on JBoss 4.0.5GA.

>No, unfortunately, there is no comparable option in SAP JPA (yet). We understand that

>there is a need for forward mapping. We would have liked to delegate this task to the

>JPA design time (i.e. Dali). However, we had to discover that Dali does not perform this

>task properly and we can't recommend using it any more.

As I'am looking for a solution to unify deplyoment to JBoss and SapNetWeaver

(maybe possible with ANT?) I hope I find a way to realize the table management also

with ANT. I have to go through the paper "Deploying J2EE Applications on SAP NetWeaver" which I found within the SAP resources.

The main problem to solve I see in the moment is the generation of the file

"META-INF\SAP_MANIFEST.MF" created on ear file generation using NWDS.

>In SAP JPA, we are always using a table generator if GenerationType.AUTO is used.

>This allows for better portability across databases. It requires the table

>TMP_SEQUENCE. As we unfortunately do not have a schema generation capability,

>the user must create this table.

Ok and thank you again for this useful information!

Best regards,

Henning Malzahn

Vlado
Advisor
Advisor
0 Kudos

Hi Henning,

> I have to go through the paper "Deploying

> J2EE Applications on SAP NetWeaver" which I found

> within the SAP resources.

Just wanted to give you a note that this paper is about SAP Web AS 6.40 and is not relevant to the Java EE 5 preview version. It also contains a disclaimer:

"There is no official support for the introduced approaches as to the deployment will be extensively refactored in SAP Web AS releases higher than 6.40. ANT Task for deployment will then be shipped right away and J2EE 1.4 compliancy will support the use of third party deployment tools as postulated in the J2EE Application Deployment Specification (JSR 88)."

> The main problem to solve I see in the moment is the

> generation of the file

> "META-INF\SAP_MANIFEST.MF" created on ear file

> generation using NWDS.

Please have a look into the C:\SAP\JP1\JC00\j2ee\deployment folder. There you will find some script files for deployment tasks, including the generation of SDA files with the corresponding META-INF\SAP_MANIFEST.MF descriptors.

Cheers,

Vladimir

Former Member
0 Kudos

Hi Vladimir,

thanks for the information - I think we're definitely putting to much information

in one thread

I'll open a new thread regarding my deployment questions tomorrow - I'm packing it in

for today.

Best regards,

Henning

Answers (0)