1 2 Previous Next 27 Replies Latest reply: May 1, 2013 11:41 AM by Arbi Sookazian RSS

Injecting with @EJB or @Inject?

jay eff Newbie
Hi all,

I've got a Wicket WebPage which is injected an EJB to retrieve the data to display in a grid. I've tried injecting the EJB with @Inject and with @EJB and both seem to work (at least for retrieving data), but a nasty error raises when using @EJB (please find the stack trace below).

My question is, which is the difference between injecting an EJB with @EJB and with @Inject? Do you lose any EJB facilities when using @Inject? Maybe I'm missing something / doing something wrong?

Thanks in advance,
J.

--------
logged error:

[#|2009-11-26T17:37:36.770+0100|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=26;_ThreadName=http-thread-pool-8080-(1);|ERROR - Objects                    - Error serializing object class controllers.QuoteBrowse [object=[Page class = controllers.QuoteBrowse, id = 0, version = 0]]org.apache.wicket.util.io.SerializableChecker$WicketNotSerializableException: Unable to serialize class: services.__EJB31_Generated__QuoteService__Intf____Bean__
Field hierarchy is:
  0 [class=controllers.QuoteBrowse, path=0]
    private services.QuoteService controllers.QuoteBrowse.quoteService [class=services.__EJB31_Generated__QuoteService__Intf____Bean__] <----- field that is not serializable
        at org.apache.wicket.util.io.SerializableChecker.check(SerializableChecker.java:346)
        at org.apache.wicket.util.io.SerializableChecker.checkFields(SerializableChecker.java:615)
        at org.apache.wicket.util.io.SerializableChecker.check(SerializableChecker.java:538)
        at org.apache.wicket.util.io.SerializableChecker.writeObjectOverride(SerializableChecker.java:684)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:322)
        at org.apache.wicket.util.io.IObjectStreamFactory$DefaultObjectStreamFactory$2.writeObjectOverride(IObjectStreamFactory.java:129)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:322)
        at org.apache.wicket.util.lang.Objects.objectToByteArray(Objects.java:1120)
        at org.apache.wicket.protocol.http.pagestore.AbstractPageStore.serializePage(AbstractPageStore.java:203)
        at org.apache.wicket.protocol.http.pagestore.DiskPageStore.storePage(DiskPageStore.java:840)
        at org.apache.wicket.protocol.http.SecondLevelCacheSessionStore$SecondLevelCachePageMap.put(SecondLevelCacheSessionStore.java:332)
        at org.apache.wicket.Session.requestDetached(Session.java:1404)
        at org.apache.wicket.RequestCycle.detach(RequestCycle.java:1176)
        at org.jboss.weld.wicket.WeldRequestCycle.detach(WeldRequestCycle.java:155)
        at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1454)
        at org.apache.wicket.RequestCycle.request(RequestCycle.java:545)
        at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:468)
        at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:301)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:277)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
        at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
        at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
        at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
        at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:332)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:233)
        at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
        at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
        at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
        at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
        at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:168)
        at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
        at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
        at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
        at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
        at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
        at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
        at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
        at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
        at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
        at java.lang.Thread.run(Thread.java:619)
Caused by: java.io.NotSerializableException: services.__EJB31_Generated__QuoteService__Intf____Bean__
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
        at org.apache.wicket.util.io.IObjectStreamFactory$DefaultObjectStreamFactory$2.writeObjectOverride(IObjectStreamFactory.java:121)
        ... 37 more
|#]

------------

The WebPage class is controllers.QuoteBrowse and the EJB is services.QuoteService.
  • 1. Re: Injecting with @EJB or @Inject?
    Gavin King Master

    That error is very strange, since EJB local references should always be serializable. Bug in glassfish, perhaps?


    Basically, @Inject is always better, since:



    • it is more typesafe,

    • it supports @Alternatives, and

    • it is aware of the scope of the injected object.



    I recommend against the use of @EJB except for declaring references to remote EJBs.

  • 2. Re: Injecting with @EJB or @Inject?
    Seto Kaiba Newbie

    I wonder whether weld just as Seam 2.x still doesn't support the injection of the remote EJBs.

  • 3. Re: Injecting with @EJB or @Inject?
    Nicklas Karlsson Master

    Introduction of chapter 3 in the 299 spec:


    The container provides built-in support for injection and contextual lifecycle management of the following kinds of bean:
    ...
    Resources (Java EE resources, persistence contexts, persistence units, remote EJBs and web services)
    

  • 4. Re: Injecting with @EJB or @Inject?
    Seto Kaiba Newbie

    Nicklas Karlsson wrote on Nov 28, 2009 21:32:


    Introduction of chapter 3 in the 299 spec:

    The container provides built-in support for injection and contextual lifecycle management of the following kinds of bean:
    ...
    Resources (Java EE resources, persistence contexts, persistence units, remote EJBs and web services)
    




    It's interesting that the spec mentioned the resources in chapter 3 while the weld doc didn't mention the resources in the chapter 2 ending with the last producer fields.


    This is the feature defined in the spec. Is it available with Weld at the same time?

  • 5. Re: Injecting with @EJB or @Inject?
    Seto Kaiba Newbie

    If it is supported in Weld at the same time, which is better for using to inject remote beans. I'm just confused by gavin's words I recommend against the use of @EJB except for declaring references to remote EJBs. Does it mean @EJB better with remote EJBs?

  • 6. Re: Injecting with @EJB or @Inject?
    Gavin King Master

    Use @EJB to define a resource. Then inject it into your beans using @Inject.

  • 7. Re: Injecting with @EJB or @Inject?
    Gavin King Master

    Does it mean @EJB better with remote EJBs?

    For a remote EJB, we can't declare metadata like qualifiers, @Alternative, etc, on the bean class, since the client simply isn't going to have access to that metadata. Furthermore, some additional metadata must be specified that we don't need for the local case (global JNDI name of whatever). So all that stuff needs to go somewhere else: namely the @Produces declaration.


    Does that make sense?

  • 8. Re: Injecting with @EJB or @Inject?
    jay eff Newbie

    OK Gavin, thanks for helping.


    Rgds,
    J.

  • 9. Re: Injecting with @EJB or @Inject?
    Seto Kaiba Newbie

    Thanks for replying. I understand now.

  • 10. Re: Injecting with @EJB or @Inject?
    Arbi Sookazian Master

    B/c I am stupid, I like platform and fmwks that cater to the KISS principle.


    This is not happening here.


    IMHO, it seems somewhat strange that we must decide b/n using @Inject and @EJB in EE 6 apps.


    Ok, so there seems to be a technical limitation in the case of remote EJBs.  But it would have been nice if the EGs somehow eliminated @EJB completely (except for backwards-compatibility for EE 5 apps).


    Unfortunately, now it's somewhat confusing and/or you must keep track of yet another rule/detail so you know when to use which annotation....  bah humbug!

  • 11. Re: Injecting with @EJB or @Inject?
    Gavin King Master

    B/c I am stupid, I like platform and fmwks that cater to the KISS principle.

    This is not happening here.

    Arbi, if you spent more time on the learning and understanding bit, and less time on the criticizing stuff you don't properly understand bit, you would not be so stupid.



    IMHO, it seems somewhat strange that we must decide b/n using @Inject and @EJB in EE 6 apps.

    Four posts ago, I gave you a very simple piece of advice, so that you don't need to decide anything. I wrote:



    Use @EJB to define a resource. Then inject it into your beans using @Inject.

    Other people seem to have understood what I wrote. If you don't understand, why not ask for further explanation, instead of shooting your mouth off?



    Ok, so there seems to be a technical limitation in the case of remote EJBs. But it would have been nice if the EGs somehow eliminated @EJB completely (except for backwards-compatibility for EE 5 apps).

    @EJB is completely eliminated for local EJBs (except for backward compatibility). There are lots and lots of examples in the CDI spec and Weld documentation of using @Inject to inject local EJBs. And lots of times where I've explained that we strongly recommend the use of @Inject instead of @EJB to inject local EJBs. How could you possibly have missed that? Because you were too busy posting questions and brain-dead criticism instead of actually reading what is already out there?


    And if we tried to eliminate @EJB for remote EJBs, then we would need to introduce some new annotation, let's call it @ArbisSpecialEJB in order to tell the container where to go to obtain the reference to the remote EJB. And, of course, @ArbisSpecialEJB would need basically the same members that @EJB already has. Hey, I've got an idea! Why don't we just eliminate @ArbisSpecialEJB and use @EJB for that instead! After all, @EJB already exists and has a shorter name.



    Unfortunately, now it's somewhat confusing and/or you must keep track of yet another rule/detail so you know when to use which annotation.... bah humbug!

    It's confusing to some people, apparently.

  • 12. Re: Injecting with @EJB or @Inject?
    Gavin King Master

    Jesus, in my very first reply in this thread, I wrote:



    Basically, @Inject is always better ... I recommend against the use of @EJB except for declaring references to remote EJBs.

    I don't know how I could possibly have been more explicit.

  • 13. Re: Injecting with @EJB or @Inject?
    jay eff Newbie
    I tweaked the code a bit to try to generalize table-browsing Wicket pages (the R in CRUD, that is). One change I had to do is to define an interface the stateless local EJBs must implement so that field sorting, paging, etc. works seemlessly -- all this is very, very inelegant yet, just concept stuff... :)

    The problem is that injecting EJBs in Wicket pages is now broken in my app. This is how I used to declare the service (EJB) class before the changes and how it was injected (this worked):
    ==
    @Stateless
    public class QuoteService { ...
    --
    public class QuoteBrowse extends WebPage {
      @Inject private QuoteService quoteService;
      ...
    ==

    And this is how the code looks now for the EJB (the code to inject it hasn't changed):
    ==
    @Stateless
    public class QuoteService implements BrowseableService { ...
    ==

    So now I'm getting the following error in GlassFish v3 b73 during deployment:
    ==
    [#|2009-12-02T13:53:00.315+0100|SEVERE|glassfishv3.0|javax.enterprise.system.core.com.sun.enterprise.v3.server|_ThreadID=24;_ThreadName=http-thread-pool-4848-(2);|Exception while loading the app
    org.glassfish.deployment.common.DeploymentException: Injection point has unstatisfied dependencies. Injection point: field controllers.QuoteBrowse.quoteService; Qualifiers: [@javax.enterprise.inject.Default()]
            at org.glassfish.weld.WeldDeployer.event(WeldDeployer.java:169)
            at org.glassfish.kernel.event.EventsImpl.send(EventsImpl.java:88)
            at org.glassfish.internal.data.ApplicationInfo.start(ApplicationInfo.java:239)
            at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:339)
            at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:183)
            at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:272)
            at com.sun.enterprise.v3.admin.CommandRunnerImpl$1.execute(CommandRunnerImpl.java:305)
            at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:320)
            at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1176)
            at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$900(CommandRunnerImpl.java:83)
            at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1235)
            at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1224)
            at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:365)
            at com.sun.enterprise.v3.admin.AdminAdapter.service(AdminAdapter.java:204)
            at com.sun.grizzly.tcp.http11.GrizzlyAdapter.service(GrizzlyAdapter.java:166)
            at com.sun.enterprise.v3.server.HK2Dispatcher.dispath(HK2Dispatcher.java:100)
            at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:245)
            at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
            at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
            at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
            at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:168)
            at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
            at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
            at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
            at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
            at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
            at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
            at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
            at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
            at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
            at java.lang.Thread.run(Thread.java:619)
    Caused by: org.jboss.weld.DeploymentException: Injection point has unstatisfied dependencies. Injection point: field controllers.QuoteBrowse.quoteService; Qualifiers: [@javax.enterprise.inject.Default()]
            at org.jboss.weld.Validator.validateInjectionPoint(Validator.java:232)
            at org.jboss.weld.Validator.validateBean(Validator.java:80)
            at org.jboss.weld.Validator.validateRIBean(Validator.java:100)
            at org.jboss.weld.Validator.validateBeans(Validator.java:282)
            at org.jboss.weld.Validator.validateDeployment(Validator.java:268)
            at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:389)
            at org.glassfish.weld.WeldDeployer.event(WeldDeployer.java:166)
            ... 30 more
    |#]
    ==

    But it works if I inject the service in a BrowseableService (the interface) type instead of a QuoteService (@Inject private BrowseableService quoteService;).

    On the other hand, the Weld Reference PDF sates:
    "A bean type is a user-defined class or interface; a type that is client-visible. If the bean is an EJB session bean, the bean type is the @Local interface or bean-class local view."

    So the new code should work because the QuoteService is still a "bean-class local view", right? I'm a bit confused, should the EJB implement a @Local interface for this to work? Any help would be appreciated.

    BTW, sorry for these lengthy posts.

    Rgds, J.
  • 14. Re: Injecting with @EJB or @Inject?
    William Drai Newbie

    It seems more or less related to WELD-305, but I'm not sure that my patch will help you if you don't have a local interface.

1 2 Previous Next