Skip to Content
0
Former Member
Feb 04, 2009 at 12:56 PM

Using JPA Entity-Objects defined in other EJB-Development Component

82 Views

Hello Community,

I'm working on a Java-Application on NW CE 7.1, using JEE5 Beans in the Business-Logic-Layer and WebDynpro/Java in the UI-Layer.

I designed a Bean for working with data, stored in a database-table of the system-database.

For that addtionally i created a class, representing the Entity-Object, in the same Development-Component of Type EJB 3.0.

It looks like this:

@NamedQueries ({
	@NamedQuery (name="findAllSdCust", query="SELECT c from SdCust c ORDER BY c.kdnr"),
	@NamedQuery (name="findSdCustByKdnr", query="SELECT c from SdCust c WHERE c.kdnr = :kdnr"),
	@NamedQuery (name="findSdCustByIlnnr", query="SELECT c from SdCust c WHERE c.ilnnr = :ilnnr")
})
@Entity
@Table(name="ZKALL_SD_CUST")
public class SdCust implements Serializable {

	@Id
	@TableGenerator (name="idGenerator", table="ZKALL_ID_GEN", pkColumnName="GEN_KEY", valueColumnName="GEN_VALUE", initialValue=100)
	@GeneratedValue (strategy=GenerationType.TABLE, generator="idGenerator")
	private long id;
	private String name;
	private String lname;
	private String kdnr;
	private String ilnnr;
	private long connid;
	private long cnt;
	@Version
	private long version;
    
       ..... 
      Constructor, Getter and Setter methods follow here
       .....
}

The corresponding bean looks like this

@Stateless(name="SdCustBean")
public class SdCustBean implements SdCustLocal {

	@PersistenceContext (unitName="xyz")
	private EntityManager em;

	public SdCust getSdCustByKdnr (String kdnr)
	{
		SdCust result = new SdCust();
		// List<Manufacturer> resultList = new ArrayList<Manufacturer>();
		Query  myQuery = em.createNamedQuery("findSdCustByKdnr");
		myQuery.setParameter("kdnr", kdnr);
		result = (SdCust) myQuery.getSingleResult();
		return result;
	}

	public void setEM (EntityManager iem)
	{
		em = iem;
	}

       // other methods .....

}

After that i created a new Development-Component of Enterprise Application-Type and added above DC to this EAR-DC. I also supplied the nessecary descriptor-files/Enries in EJB-DC and EAR-DC.

When now using this bean from WebDynpro with the Web-Dypro EJB-Model-Import everything works fine.

The bean returns the desired object(s).

But now i created a new DC of type EBJ 3.0

This DC contains a Message Driven Bean. That MDB is a Job-Bean which i want to schedule. That Bean uses JRA to connect to an SAP-Abap-System to read some Data and should use JPA to insert/upate/delete the read data in the Database. This should work as a simple replication for my application.

I assigned that EJB-DC containing the MDB to a new EAR-DC together with job-definition-xml and the neccessary entries in deployment-descriptors.

After deploying i see the corresponding job-defition in the NW scheduler using the administrator-views.

I'm also able to schedule the job and it executes fine. Connecting to SAP-Abap System also works fine using JRA.

But JPA does not work!!!!!

I created an dependency from my EAR-DC containing the Job EJB-DC and to the EJB-DC containing the Entity-Class.

I tried three diferent things to get i running, but all of them failed.

1.)

The part looks like:

...
public class MasterDataReplicateJobBean extends MDBJobImplementation implements MessageListener
 {
  @EJB SdCustBean mybean;
  
   public void onJob(JobContext ctx) throws Exception {
    ....
        SdCust sdCust = mybean.getSdCustByKdnr (mykdnr);
   }		
}

Compiles fine. But this fails because the Data is stored in the system-database. The exception says, that i have to use a datasource which supports 2-Phase commit. I know, that i could possibly solve this problem by annotation the Method getSdCustByKdnr with the Annotation for the Transaction-Manager to use REQUIRES_NEW Transaction. But i dont want to generally annotate my methods this way.

2.)

This part looks like this

...
public class MasterDataReplicateJobBean extends MDBJobImplementation implements MessageListener
 {

 @PersistenceContext (unitName="xyz")
 private EntityManager em;
  
   public void onJob(JobContext ctx) throws Exception {
    ....
	SdCust cust = new SdCust();
	Query  myQuery = em.createQuery("SELECT c from SdCust c WHERE c.kdnr = :kdnr");
	myQuery.setParameter("kdnr", dbkdnr);
	cust = (SdCust) myQuery.getSingleResult();
    ....
   }		
}

This also results in a runtime-exception because the entity-Manager cant resolve SdCust from the Query as an Object. The Exception is:

java.lang.IllegalArgumentException: line 1: Abstract Schema Type 'SdCust' doesn't exist
SELECT c from SdCust c WHERE c.kdnr = :kdnr

3.) and last try so far:

...
public class MasterDataReplicateJobBean extends MDBJobImplementation implements MessageListener
 {

 @PersistenceContext (unitName="xyz")
 private EntityManager em;
  
   public void onJob(JobContext ctx) throws Exception {
    ....
	SdCustBean custBean = new SdCustBean();
	custBean.setEM(em);
	SdCust cust = custBean.getSdCustByKdnr(kdnr);
    ....
   }		
}

In this example i use the Bean from the beginning not as a bean itself but as a normal class. that class has an addtional Method setEM to set the Entity-Manager (which is injected when using the class as a bean)

In that way i got the exception, that the named Query "findSdCustByKdnr" cannot be found by the entity-manager.

It seems to me, that i can access the class, but that all annotations belonging to JPA for that class are not recognized.

Does anybody can give me a hint to solve this problem? Did i forgot something important?

best regards

matthias hayk

Edited by: Matthias Hayk on Feb 5, 2009 9:38 AM