cancel
Showing results for 
Search instead for 
Did you mean: 

ClassCastException Occurs After Lookup Operation

Former Member
0 Kudos

Hi !

I deployed a EJB3 session bean (as an EAR1) on the NW7.1.

The aim is to call this EAR1 from another session bean (EAR2), which is also on the server deployed.

The EAR2 bean do I call from a stand allone java client on my PC to test it. The call of the EAR2 from the stand alone client works fine so far, if the EAR1 is called not yet(only for testing) from the EAR2.

The code of the stand allone java client is:


...
try{	
			
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sap.engine.services.jndi.InitialContextFactoryImpl");
props.put(Context.PROVIDER_URL, "10.253.17.23:50004");
props.put(Context.URL_PKG_PREFIXES, "com.sap.engine.services");   		
Context ctx = new InitialContext(props);
Object o = ctx.lookup("ejb:/interfaceName=de.itinformatik.mes.IFs.WorkerClient1Remote");
WorkerClient1Remote ref = (WorkerClient1Remote)PortableRemoteObject.narrow(o, WorkerClient1Remote.class);
System.out.println("-->"+ ref.sayHello());
...

Now here the code of the EAR2, which should call the EAR1 over its remote interface:


...
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sap.engine.services.jndi.InitialContextFactoryImpl");
props.put(Context.PROVIDER_URL, "10.253.17.23:50004");
props.put(Context.URL_PKG_PREFIXES, "com.sap.engine.services");   		
		
Context ctx = new InitialContext(props);
Object o = ctx.lookup("ejb:/interfaceName=de.itinformatik.mes.IFs.WorkerRemote");
WorkerRemote ref = (WorkerRemote) PortableRemoteObject.narrow(o, WorkerRemote.class);
return ref.sayHello();
...

But now, if I call the EAR2 and it continiues to call the EAR1 , I get an exception at the WorkerRemote ref = (WorkerRemote) PortableRemoteObject.narrow(o, WorkerRemote.class) line in the EAR2:


"	
Caused by: java.lang.ClassCastException: de.itinformatik.mes.IFs.WorkerRemote
	at com.sap.engine.services.cross.PortableRemoteObjectContainer.narrow(PortableRemoteObjectContainer.java:219)
	

....

I dont understand, why the call from the EAR2 to the EAR1 is not working.

Can anybody help please ?

I guess there is a hint:

http://help.sap.com/saphelp_nw04/helpdata/EN/4d/993441c73cef23e10000000a155106/frameset.htm

but I cant fix the problem.

many thanks,

Hendrik

Accepted Solutions (1)

Accepted Solutions (1)

siarhei_pisarenka3
Active Contributor
0 Kudos

Hello Hendrik

First of all if the two DC are deployed on the same system why do you need the remote interface. Try to use the local interface without narrowing.

How are U established a reference from EJB2 DC to EJB1 DC?

BR.

Sergei

Former Member
0 Kudos

Hi Sergie,

Yes, you are right, the remote interface is not needed, when I use the two beans on the the same system.

But my project requires the function to communicate about the remote interface although the two beans are running on the same container or system.

How are U established a reference from EJB2 DC to EJB1 DC?

I am not sure, if I understand your question right.

How the reference is established between the two beans you can see on my code snipets posted above.#

The EJB1 was build as an bean which can be called over the remote interface:

The interface:

@Remote

public interface WorkerRemote {

public String sayHello();

.....

The impl class:

public class WorkerBean implements WorkerRemote {

public String sayHello() {

return "###hello###";

}

The call to the EJB1 you can see at the snipets shown above.

Many thanks for reply and greetz,

Hendrik

siarhei_pisarenka3
Active Contributor
0 Kudos

Hi Hendrik

You told that you had two DCs: EAR1 and EAR2. In SAP J2EE there must be a reference from one DC to another which is established via DC public parts. With help of the reference you are referencing EAR1's Java classes from EAR2.

Interface WorkerRemote must be part of some public part in EAR1. EAR2 have to reference the PP.

It might happen that actually you have two copies of WorkerRemote. One is in EAR1 and onother one is in EAR2. Then you'll get ClassCastException like in your case. This is wrong way. Try to inspect the two EARs and ensure that you have a single copy of WorkerRemote.

BR, Sergei

Former Member
0 Kudos

Hello Sergei !

Yes, indeed the WorkerRemote interface exists two times. I try to explain what the matter is:

-> the first WorkerRemote interface is in the EAR1. There it is needed to define the interface as remote and to use it to call the EAR1 application over the interface.

here the code of my interface in EAR1:


public interface WorkerRemote {
public String sayHello();
....

here the code of my implementation class in EAR1:


@Remote(WorkerRemote.class)
public class WorkerBean implements WorkerRemote {


	public String sayHello() {
		return "###hello###";
	}

->Ok, and now I build a WorkerBeanInfo.jar, which includes the WorkerRemote interface from the EAR1.

This jar file I include in the EAR2 project build path, so that the following call from EAR2 to the remote interface in EAR1 can be done:


Context ctx = new InitialContext(props);
Object o = ctx.lookup("ejb:/interfaceName=de.itinformatik.mes.IFs.WorkerRemote");
WorkerRemote ref = (WorkerRemote) PortableRemoteObject.narrow(o, WorkerRemote.class);
return ref.sayHello();
...

I guess that the WorkerBeanInfo.jar in the EAR2, the caller for EAR1, is needed, so that I can use the code: "WorkerRemote ref = (WorkerRemote) PortableRemoteObject.narrow(o, WorkerRemote.class);"

So the WorkerRemote interface exsits 2 times, in EAR1 as the common remote interface and in EAR2 in the WorkerBeanInfo.jar . But the problem is i guess, that the EAR2 needs the WorkerRemote Interface provided in the WorkerBeanInfo.jar, otherwise there will be a ClassNOtFound Exception.

I see the problem are the two WorkerRemoteInterfaces, but I have no idea, what to do to omit one of the WorkerRemoteInterfaces.

Thank you so far,

Hendrik

Edited by: henne123 on Jun 2, 2009 4:11 PM

siarhei_pisarenka3
Active Contributor
0 Kudos

Hi Hendrik

Yep, having two WorkerRemote interfaces causes the problem. You have to configure your projects in the following way:

- EAR1 project contains WorkerRemote and produces WorkerBeanInfo.jar. The EAR shall assembly the JAR. This can be done if you create the corresponding public part in the DC.

- EAR2 project just references WorkerBeanInfo.jar in order to build the code. It shall not assembly the JAR into EAR. This can be done if you reference the public part from DC1. The reference type shall be 'compilation', not 'assembly'.

- On runtime EAR1 shall also reference EAR2 (WorkerBeanInfo.jar) and load the WorkerRemote interface from the JAR. This can be done if you setup a runtime reference DC2->DC1.

BR, Sergei

Former Member
0 Kudos

Hi Sergei,

sorry to stress you again

Please have a look, what I tried to solve the prob.

- EAR2 project just references WorkerBeanInfo.jar in order to build the code. It shall not assembly the JAR into EAR. This can be done if you reference the public part from DC1. The reference type shall be 'compilation', not 'assembly'

Do you mean the reference to build the code is to configure over the project settings in the Developer Studio?

I did the following: In project settings of the EAR2->Java Build Path-> in the tap "Projects" I addad the EAR1 project. So the EAR2 could built without the WorkerBeanInfo.jar.

On runtime EAR1 shall also reference EAR2 (WorkerBeanInfo.jar) and load the WorkerRemote interface from the JAR. This can be done if you setup a runtime reference DC2->DC1.

Is this "runtime reference" to be done over anotations ? Or over a JNDI lookup ? I dont understand what you exactly mean with "runtime reference". The only runtime reference at EJB3 I know is like the JNDI lookup to search for resources.

Thank you for your effort !!

Hendrik

siarhei_pisarenka3
Active Contributor
0 Kudos

HI Hendrik

Yes, I think your solution with project reference will work.

Regarding a runtime reference.. In SAP J2EE all the development/deployment is performed over development components (DC). You may consider DC as a wrapper over Java project. So the references are managed between two development components in IDE.

In your case I see that you are not developing DCs, but rather standard Eclipse's J2EE projects. In this case you can try to add to EAR2 the special file application-j2ee-engine.xml with references:

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

<application-j2ee-engine xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="application-j2ee-engine.xsd">

<reference reference-type="hard">

<reference reference-type="hard">

<reference-target provider-name="sap.com" target-type="application">EAR1 application name</reference-target>

</reference>

<provider-name>sap.com</provider-name>

<fail-over-enable mode="disable" xsi:type="fail-over-enableType_disable"/>

<start-up mode="lazy"/>

</application-j2ee-engine>

Former Member
0 Kudos

Hi Sergei !

Many, many thanks for your help, it works !!!

Perhaps a few lines to explain:

I created real EJB3 projects in the developer studio over the wizzard from the beginning of my work with it and so the application-j2ee-engine.xml was already in the project. The runtime reference you wrote about works perfect and the project reference from EAR2 to EAR1 too.

the WorkerBeanInfo.jar was not longer necessary, also not in the EAR1. through the runtime reference in the application-j2ee-engine.xml the WorkerRemote Interface is found during execution.

I know this configuration files like the application-j2ee-engine and the ejb-j2ee-engine.xml for example but I was realy doubtful, whether to use these ones or not. I thougt they are only for EJB2.1 and in EJB3 no more

necessary.

A lot ot learn for me...

Ok, thank you again and greetz,

Hendrik

Answers (1)

Answers (1)

ekaterinamitova
Advisor
Advisor
0 Kudos

Hi Hendrik,

As you use a remote interface you should probably use the EJB Lookup Scheme:

http://help.sap.com/saphelp_nwce711/helpdata/EN/45/e692b2cfaa5591e10000000a1553f7/frameset.htm

I hope this works.

Best regards,

Ekaterina

Former Member
0 Kudos

Hi Ekaterina,

I used already the code, which is on the sap help webside you posted.

Here a snipet:


...
public class WorkerClient1Bean  implements WorkerClient1Remote  {
	public String sayHello() 
	{
		System.out.println (">>>EJB-Client  callBackRemote() Start");


		Properties props = new Properties();
		props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sap.engine.services.jndi.InitialContextFactoryImpl");
		props.put(Context.PROVIDER_URL, "10.253.17.23:50004");
		props.put(Context.URL_PKG_PREFIXES, "com.sap.engine.services");   		
			
		try {
			Context ctx = new InitialContext(props);
			Object o = ctx.lookup("ejb:/interfaceName=de.itinformatik.mes.IFs.WorkerRemote");
			WorkerRemote ref = (WorkerRemote) PortableRemoteObject.narrow(o, WorkerRemote.class);
			
WorkerRemote ref  =(WorkerRemote)ctx.lookup("ejb:/interfaceName=de.itinformatik.mes.IFs.WorkerRemote");
return ref.sayHello()

This works already for my stand alone java client.

But the problem is, that the call of the EJBs among each other dont work. There occurs the ClassCastException in the codeline where the cast to the interface is done. (..WorkerRemote) PortableRemoteObj..)

Best regards,

Hendrik