cancel
Showing results for 
Search instead for 
Did you mean: 

calling an EJB from User Defined Ffunction

Former Member
0 Kudos

Hi there,

I have requirements to implement a global message counter. The counter value has to be placed in the target message that leaves XI.

Therefore, my intetniton was to implement an EJB and store that counter value to database.

The problem is the lookup of that EJB from my User Defined Function, which ends up in a java.lang.reflect.InvocationTargetException.

Is there any possibility for calling EJB from UDF or does XI provide an built-in solution for the "global counter problem"?

Any help is highly appreciated and will be rewarded! Thanks in advance.

Cheers,

Matthias

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos

Answers (5)

Answers (5)

Former Member
0 Kudos

Hi Matthias,

obviously you want to hold some kind of state on the Integration Server. By design of XI mapping should be stateless. The normal place to keep state in the Integration Server is ccBPM.

Hence, even if you get the solution you have in mind working (using a bean to persist the state on the java part of the Integration Server via a bean) I would not recommend to do so. It would just be luck and future changes done by SAP could invalidate this solution.

A little bit more stable would be the solution already suggested utilizing an external database to store the state via Lookup-api and jdbc-adapter. However, I also see problems with this solution.

What happens e.g. when your mapping fails with an exception (e.g. Out-of-memory) when the external counter has already been incremented. Maybe you will restart the mapping after having solved your resource problem and the counter will be incremented once more.

I think ccBPM was just designed to have a robust solution for that task.

Greetings Stephan

Former Member
0 Kudos

Ok, thanks for all you replies. Next weeks I'm on vacations, but afterwards I'll evaluate your recommendations for an appropriate solution.

cu

Matthias

Former Member
0 Kudos

Hi again,

just want to tell that I'm still having that problem. It seems that no EJB lookup is possible from User Defined Function. We're still working on SP16. Maybe this is the reason?

Anyway, I'm currently thinking about a workaround: A placeholder for the counter variable is written to the target file while mapping, and a module in outgoing communication channel substitutes that placeholder with the variable's value.

If anybody still have an idea how to solve the original problem, help is still highly apreciated.

Cheers,

Matthias

STALANKI
Active Contributor
0 Kudos

Guess you missed the import statement.

Former Member
0 Kudos

Sravya,

the import is done. Sorry, I forgot to tell, that the lookup isn't done directly within the UDF, but in a imported singleton class.

The UDF code is like that

return GlobalVariablesProvider.getInstance().getIncrementedCounter("test").toString();

The singleton class should call the EJB get the counter, increment the value and return the value as an Integer back to UDF.

The imports are ok. I can track the code within the debugger.

Former Member
0 Kudos

Me again )

Do I have to narrow to the EJB class or to the Stub class?

Former Member
0 Kudos

Hi Mathias,

I had exactly the same requirement few months back. I had developed a function module on the abap stack of XI which tracks the counter and saves it in a table. As it is saved in a table, it is persistant. i made lookups to this table using the XI adapter. this was very fast as it doesnät include any calls to the external system as the table is whithin the ABAP stack of XI.

Hope this helps.

Anil

Former Member
0 Kudos

Hi,

>>Do I have to narrow to the EJB class or to the Stub class?

To the stub class... You need stud class to be imported in Repository only for this reference.

There wont be any difference if you do the lookup in imported singleton class or in UDF.

I think your lookup is not correct. It should have the EJB name which is deployed in the server... only then it can find this class GlobalVariablesServiceLocalHome.

And, the ref object which is passed as parameter for narrow() should not be used for casting. Modify your code like this...

serviceHome = (GlobalVariablesServiceLocalHome)PortableRemoteObject.narrow(

ref,

GlobalVariablesServiceLocalHome.class);

The import statement for this class should be with package name (for default package not needed).

Regards,

Uma

Former Member
0 Kudos

Uma,

thank you for your help!!!

I did it as you recommended. Now I get a NoClassDefFoundError. I had a look into my generated client jar. This is only containing the "*_Stub.class"-es. Is this enough? Are there no skeletons needed?

Thank you again.

Regards,

Matthias

Former Member
0 Kudos

Uma,

another thing:

I can debug the singleton class from my NWDS.

The line

jndiContext.lookup("GlobalVariablesService")

returns a object of type

ObjectReferenceImpl

The next debug step

PortableRemoteObject.narrow(ref, GlobalVariablesServiceHome.class);

results in an InvocationTargetException.

Any clue?

Former Member
0 Kudos

Hi,

Can u check if these are the import statement which u have used?

javax.naming.InitialContext

javax.naming.Context

javax.rmi.PortableRemoteObject

Regards,

Ums

Former Member
0 Kudos

Uma,

imports are ok.

Which code is correct:

PortableRemoteObject.narrow(ref, GlobalVariablesServiceHome_Stub.class);

or

PortableRemoteObject.narrow(ref,GlobalVariablesServiceHome.class);

Or should I use the local interfaces?

Former Member
0 Kudos

Hi,

The class inside the jar which is imported in Repository should be used in narrow().

The EJB will have following ...

Bean

Local

LocalHome

Remote

Home

The EJB jar containing these files should be deployed in XI Server.

Another jar with stubs i.e., Local and LocalHome should be imported in Repository.

In narrow(), use this Local interfaces

Regards,

Uma

STALANKI
Active Contributor
0 Kudos

then i think u can use ejb and jar it and importand use it.

Former Member
0 Kudos

Sravya,

that's what I tried. But this leads into a ClassCastException. The ejb is accesable systemwide with its JNDI name. Lookup seems to work, but narrowing to the jared ejb interface causes that exception. It seems there's a different classloader for mapping functions. Is there any possibility to bring the ejb stubs to the mapping?

Thank you again!

Cheers,

Matthias

Former Member
0 Kudos

Hi,

After creating EJB, build a new EAR and deploy this EAR in Server.

In User Defined function, lookup the ejb using EAR and EJB name.

Jar ur EJB stubs and import this Jar into repository. This is needed for the User defined function to refer the LocalHome and Local interfaces.

Use this code for creating LocalHome object...

<localHome> localhome = (<LocalHome>)PortableRemoteObject.narrow(

ob,<LocalHome>.class);

<Local> local = (<Local>) localhome.create();

{here ob refers to lookup object.}

Regards,

Uma

Message was edited by:

Uma Maheswari Soundara Pandian

Former Member
0 Kudos

Uma,

maybe I'm too stupid to do so. If followed your guidance and created the client jar (including stubs) with Deploy service of Visual Admin. Then I uploaded this jar to Integration Repository.

Now, the PortableRemoteObject.narrow fails with an NoClassDefFoundError

The lookup code is done like that:


Context jndiContext;
jndiContext = new InitialContext();
Object ref = jndiContext.lookup("GlobalVariablesService");
PortableRemoteObject.narrow(
	ref,
	GlobalVariablesServiceLocalHome.class);
	serviceHome = (GlobalVariablesServiceLocalHome) ref;

Do you have any further hints for me? Please help...

Cheers,

Matthias

STALANKI
Active Contributor
0 Kudos

write a simple class with static attribute counter.compile it and import the jar file into the imported archive OF UR swcv.

import the jar in UDF.u can access the class.simple.

Former Member
0 Kudos

Hi all,

thank you very much for your replies!

@ Mario: Your're thinking about an JDBC communication channel, that writes database records. Looks interesting, but for input reading i'll need BPM?

@ Dennis: Lookup API seemst to be a good solution. I've already read the API Docs and I'll try it today. I'll report the solution...

@ Sravya: for my counter, I need persistence. Because it should count overall messages to an business partner. Thus, a resetted counter after a system restart wouldn't solve the problem.

Thanks again & I let you know.

Regards,

Matthias

Former Member
0 Kudos

Hi Matthias

<Looks interesting, but for input reading i'll need BPM?>

---> What do you mean by <input reading>

Regards Mario

Former Member
0 Kudos

Mario,

I need the counter value within the processed message. Therefore i have to call the value from a mapping.

Thank you!

Cheers,

Matthias

Former Member
0 Kudos

OK, seems you need BPM!

Regards Mario

Former Member
0 Kudos

Hi Matthias,

I would solve it in another ay. A special backend system should provide a service "counter" or use a database to insert a special record.

Now in every receiver determination call the defined service or make a insert in the database.

Regards Mario