Skip to main content

JAX-RS in GF 2.1 and EJB injection?

12 replies [Last post]
rsoika
Offline
Joined: 2006-12-09

I just started to implement a JAX-RS REST service in GF 3.
My implementation need to access EJBs which are deployed in the surrounding EAR of my WAR file.
To use the dependency injection (@EJB) I read about the need to add a @stateless annotation to my RESTservice class :

@Path("/workflow")
@Produces( { "application/xml","application/json" })
@Stateless
public class WorkflowServiceHandler {
@EJB
org.imixs.workflow.jee.ejb.WorkflowService workflowService;

@GET
@Path("/worklist/")
public EntityCollection getWorkList(@DefaultValue("0") @QueryParam("start") int start,@DefaultValue("10") @QueryParam("count") int count ) {
Collection col = null;
try {
col = workflowService.getWorkList(null, start, count);
return buildEntityCollection(col);

} catch (Exception e) {
e.printStackTrace();
}
return new EntityCollection();
}
...

This works as expected in Glassfish V3.
But now I try to get this run on a GF V2.1 server. I have added the jersey-core-1.1.5.1 and jersey-server-1.1.5.1 jars. So basically I have the functionality of jersey up and runing.

But the problem is the injected EJB in my code example. As I understand this will only work in GF 3 Server.

Now I want to ask if anybody have a solution for such a problem? I found this blog about a possible solution in GF 2.1:
http://blogs.sun.com/sandoz/entry/ejb_injection

But my problem is that I did not finally understand what I should do to get things run in GF 2.1.
Did anybody solved this situation yet?
Is it necessary/recommended to implement a EJB Provider class subclassed from the com.sun.jersey.spi.inject.InjectableProvider ?

I still did not found any working solution :(
Thanks for any help

Ralph

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Paul Sandoz

On Apr 21, 2010, at 11:29 AM, glassfish@javadesktop.org wrote:

> Hi Witold,
> Hi Paul,
>
> thanks for your replies. I will try this again. I thought that I
> still tried this szenario. My EJBs are separated in jars and
> provided in the root of my EAR (the ejbs are used also by an
> additional web main application).
> The main different in my test seems to be that I always tried to
> inject the local inferfaces form my EJBs - like I do in a servlet or
> JSF managedBean class.
> But you do inject the remote interface in your example.
> Its this the trick to inject the remote interface and not the local
> interface?
>

Yes.

With some experimentation i think i have found a way to get lookup
working with local beans. See attached for a modified version of
web.xml and EJBProvider.

You need to ensure the ejb-ref-name is the class name of the local
interface.

Note that i will need to fix a bug in Jersey if you want the local
bean reference to be a root resource class itself.

Paul.

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd
">

Jersey Web Application
class>com.sun.jersey.spi.container.servlet.ServletContainer class>

com.sun.jersey.config.property.packages param-name>

org.jersey.ejb;org.jersey.web
1


Jersey Web Application
/webresources/*


org.jersey.ejb.SSBResource
Session

org.jersey.ejb.SSBResource

@Provider
public class EJBProvider implements InjectableProvider {

public ComponentScope getScope() {
return ComponentScope.Singleton;
}

public Injectable getInjectable(ComponentContext cc, EJB ejb,
Type t) {
if (!(t instanceof Class)) {
return null;
}

try {
Class c = (Class) t;
Context ic = new InitialContext();

final Object o = lookup(ic, c);

return new Injectable

() { public Object getValue() { return o; } }; } catch (Exception e) { e.printStackTrace(); return null; } } private Object lookup(Context ic, Class c) throws Exception { try { return ic.lookup(c.getName()); } catch (Exception e) { try { return ic.lookup("java:comp/env/" + c.getName()); } catch (Exception ex) { throw ex; } } } } --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net For additional commands, e-mail: users-help@glassfish.dev.java.net
rsoika
Offline
Joined: 2006-12-09

Hi,
yes your changed EJBProvider works for me now with local EJB interfaces and the EJB-REF declaration in the web.xml of my rest service module :)

ralph

Paul Sandoz

On Apr 20, 2010, at 4:55 PM, glassfish@javadesktop.org wrote:

> Hi,
> I am nobody how gives up very easily but I feel a little bit unsure
> about the solution.
> After all I did have the situation you described. I have one jar
> containing my EJB Interfaces, one jar containing my EJB
> implementations. These jars are bundled in my EAR. And I have
> defined an additional WAR containing my JAX-RS Class. This works in
> JEE6. But on JEE5 GF2.1 die @EJB annotation will be ignored. I
> added the EJBProvider. But the EJBProvider did not work. I always
> got the NameNotFound JNDI Exceptions or NameNotBound Exceptions.
> Maybe my problem is that I did not know how to add the ejb-ref
> declaration to my web.xml form my JAX-RS Implementation.
> And I can't find a complete solution or example. There are
> guidelines how to integrate jersey-server into Glassfish V2.1 but it
> seems that these guys did not work with EJBs...? :-/
>

JAX-RS 1.0 does not specify integration with EJB 3.0 nor does it
specify that root resource classes will get injected with EE-related
artifacts. Unfortunately only JAX-RS 1.1 with EE 6 does all the things
out of the box you require. JAX-RS 1.1 is not specified to work with
EE 5 in the same way.

In summary on EE 5/GF v2.1 Jersey can support:

- root resource classes that are remote interfaces of an EJB
(annotated such interfaces with JAX-RS annotations and register them).

- EE resource injection but you have to implement it yourself like the
EJBProvider does.

I have attached a simple NetBeans 6.8 enterprise application that runs
of GF v2.1. Note that it does require NB 6.8 because it makes
reference to Jersey 1.1.4 that ships with NB 6.8.

The URLs are:

http://localhost:8080/EnterpriseApplication1-war/webresources/ear
Accesses the SSB

http://localhost:8080/EnterpriseApplication1-war/webresources/war
Accesses the root resource in the war which reference the SSB.

The same app should also work on GF v3 but i have not tried it.

Hth,
Paul.

[EnterpriseApplication1.zip]

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
For additional commands, e-mail: users-help@glassfish.dev.java.net

rsoika
Offline
Joined: 2006-12-09

Hi Witold,
Hi Paul,

thanks for your replies. I will try this again. I thought that I still tried this szenario. My EJBs are separated in jars and provided in the root of my EAR (the ejbs are used also by an additional web main application).
The main different in my test seems to be that I always tried to inject the local inferfaces form my EJBs - like I do in a servlet or JSF managedBean class.
But you do inject the remote interface in your example.
Its this the trick to inject the remote interface and not the local interface?

Ralph

rsoika
Offline
Joined: 2006-12-09

Hi,

good news - jersey jax-rs works now in Glassfish 2.1 with EJB annotation :)
I am using
- jersey-core-1.1.5.1.jar
- jersey-server-1.1.5.1.jar
- jsr311-api.1.1.1.jar

to get the missing ejb injection I have added the EJBProvider you provided in your example application.
This provider works in GF2.1 and also in GF3.0 (I bundled the provider with my REST service classes)

And (very important!) I inject now the Remote Interface of my EJB not the Local Interface!

I have now two additional questions:

1. why did you not bundle this EJBProvider together with jersey-server and provide an servlet init-param to configure if the EJBProvider should be used (for JEE5) or not (for JEE6)

2. Did the fact that I am forced to use remote interfaces of my EJBs a performance issue? Did you think the the resulting code is less performance in JEE6 as if I would use the local EJB interfaces ?

Thanks for help
Ralph

Paul Sandoz

On Apr 21, 2010, at 12:12 PM, glassfish@javadesktop.org wrote:

> Hi,
>
> good news - jersey jax-rs works now in Glassfish 2.1 with EJB
> annotation :)

Great :-)

> I am using
> - jersey-core-1.1.5.1.jar
> - jersey-server-1.1.5.1.jar
> - jsr311-api.1.1.1.jar
>
> to get the missing ejb injection I have added the EJBProvider you
> provided in your example application.
> This provider works in GF2.1 and also in GF3.0 (I bundled the
> provider with my REST service classes)
>
> And (very important!) I inject now the Remote Interface of my EJB
> not the Local Interface!
>
> I have now two additional questions:
>
> 1. why did you not bundle this EJBProvider together with jersey-
> server and provide an servlet init-param to configure if the
> EJBProvider should be used (for JEE5) or not (for JEE6)
>

It's logged as an issue and i have not got around to adding it! One
thing i am reluctant to do is for Jersey to start supporting all the
EE-related injection support when we have it in EE 6 with duplication
of code but simple support @EJB seems appropriate, but I am not sure i
can actually support this as specified so it would be have to be used
under certain limitations and assumptions.

> 2. Did the fact that I am forced to use remote interfaces of my EJBs
> a performance issue? Did you think the the resulting code is less
> performance in JEE6 as if I would use the local EJB interfaces ?
>

I do not know. See my previous email for how to get local references
to work.

Paul.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
For additional commands, e-mail: users-help@glassfish.dev.java.net

Witold Szczerba

2010/4/20 :
> Hi Paul,
> thanks for your response.
> Ok as it is necessary for me that my REST Service implementation will work on JEE5 and also JEE6 I will do my implementation without JAX-RS :(  and use my Servlet implementation developed before starting my experiment with JEE6 ;-)

If you want to be JEE5 compatible, define one WAR and one EJB inside
EAR and use JAX-RS in WAR project (not in EJB like you wanted),
referencing EJBs from within your JAX-RS classes. This will suck a
little, as you will have to do write one class for JAX-RS view, one
local interface to access your EJB, like this:
app-core-api.jar -> where are EJB local interfaces and other common stuff,
app-core-ejb.jar -> the EJB module - implementation of your core API,
app-web.war -> the web module, the JAX-RS access to your application.

However it is exactly the same situation as when referencing EJBs from
within servlets, so JAX-RS or plain servlets - accessing EJBs in JEE5
can happen only through interfaces.

In JEE6 you can merge app-core-ejb.jar with app-web.war and there is
no need for app-core-api.jar in that case.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
For additional commands, e-mail: users-help@glassfish.dev.java.net

rsoika
Offline
Joined: 2006-12-09

Hi,
I am nobody how gives up very easily but I feel a little bit unsure about the solution.
After all I did have the situation you described. I have one jar containing my EJB Interfaces, one jar containing my EJB implementations. These jars are bundled in my EAR. And I have defined an additional WAR containing my JAX-RS Class. This works in JEE6. But on JEE5 GF2.1 die @EJB annotation will be ignored. I added the EJBProvider. But the EJBProvider did not work. I always got the NameNotFound JNDI Exceptions or NameNotBound Exceptions.
Maybe my problem is that I did not know how to add the ejb-ref declaration to my web.xml form my JAX-RS Implementation.
And I can't find a complete solution or example. There are guidelines how to integrate jersey-server into Glassfish V2.1 but it seems that these guys did not work with EJBs...? :-/

Ralph

Witold Szczerba

2010/4/20 :
> Hi,
> I am nobody how gives up very easily but I feel a little bit unsure about the solution.
> After all I did have the situation you described. I have one jar containing my EJB Interfaces, one jar containing my EJB implementations. These jars are bundled in my EAR. And I have defined an additional WAR containing my JAX-RS Class.

Is this WAR a part of EAR? The app-core-ejb.jar and app-web.war should
be in the root of EAR and app-core-api.jar should be in EAR/lib
directory. Is that is what you have?

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
For additional commands, e-mail: users-help@glassfish.dev.java.net

Paul Sandoz

Hi,

GF 2.1 supports EE 5 so no-interface view EJBs (or EJB POJOs) will not
work.

If you want the EJB to be a resource class in EE 5 do the following,
which is not portable and is only guaranteed to work on GF v2.x.
Define an @Remote interface and annotate that interface with JAX-RS
annotations, @Path etc, and ensure that interface is registered as a
root resource class.

If you want to inject stuff like in the blog link you sent register
that provider (e.g. make sure it is picked up using package scanning)
or declared explicitly as a class in the Application/ResourceConfig.

https://jersey.dev.java.net/nonav/documentation/latest/user-guide.html
#d4e194

Paul.

On Apr 19, 2010, at 11:20 PM, glassfish@javadesktop.org wrote:

> I just started to implement a JAX-RS REST service in GF 3.
> My implementation need to access EJBs which are deployed in the
> surrounding EAR of my WAR file.
> To use the dependency injection (@EJB) I read about the need to add
> a @stateless annotation to my RESTservice class :
>
> @Path("/workflow")
> @Produces( { "application/xml","application/json" })
> [b]@Stateless[/b]
> public class WorkflowServiceHandler {
> [b]@EJB
> org.imixs.workflow.jee.ejb.WorkflowService workflowService;[/b]
>
> @GET
> @Path("/worklist/")
> public EntityCollection getWorkList(@DefaultValue("0")
> @QueryParam("start") int start,@DefaultValue("10")
> @QueryParam("count") int count ) {
> Collection col = null;
> try {
> col = workflowService.getWorkList(null, start, count);
> return buildEntityCollection(col);
>
> } catch (Exception e) {
> e.printStackTrace();
> }
> return new EntityCollection();
> }
> ...
>
> This works as expected in Glassfish V3.
> But now I try to get this run on a GF V2.1 server. I have added the
> jersey-core-1.1.5.1 and jersey-server-1.1.5.1 jars. So basically I
> have the functionality of jersey up and runing.
>
> But the problem is the injected EJB in my code example. As I
> understand this will only work in GF 3 Server.
>
> Now I want to ask if anybody have a solution for such a problem? I
> found this blog about a possible solution in GF 2.1:
> http://blogs.sun.com/sandoz/entry/ejb_injection
>
> But my problem is that I did not finally understand what I should do
> to get things run in GF 2.1.
> Did anybody solved this situation yet?
> Is it necessary/recommended to implement a EJB Provider class
> subclassed from the com.sun.jersey.spi.inject.InjectableProvider ?
>
> I still did not found any working solution :(
> Thanks for any help
>
> Ralph
> [Message sent by forum member 'rsoika']
>
> http://forums.java.net/jive/thread.jspa?messageID=397904
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
> For additional commands, e-mail: users-help@glassfish.dev.java.net
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
For additional commands, e-mail: users-help@glassfish.dev.java.net

rsoika
Offline
Joined: 2006-12-09

Hi Paul,
thanks for your response.
Ok as it is necessary for me that my REST Service implementation will work on JEE5 and also JEE6 I will do my implementation without JAX-RS :( and use my Servlet implementation developed before starting my experiment with JEE6 ;-)

thanks for help
ralph

Paul Sandoz

On Apr 20, 2010, at 10:36 AM, glassfish@javadesktop.org wrote:

> Hi Paul,
> thanks for your response.
> Ok as it is necessary for me that my REST Service implementation
> will work on JEE5 and also JEE6 I will do my implementation without
> JAX-RS :( and use my Servlet implementation developed before
> starting my experiment with JEE6 ;-)
>

OK. Note that the solution i outlined should work on GlassFish 2.x, EE
5, and 3.x, EE 6.

Paul.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
For additional commands, e-mail: users-help@glassfish.dev.java.net