Avatar billede fredand Forsker
08. december 2016 - 15:47 Der er 11 kommentarer og
2 løsninger

Problem with local EJB call

Hello guys!

We are trying to migrate from jboss 5.0 to jboss 6.3.
We got a problem with a local ejb call, between a Webservice and a ejb.
We have tried several attempts and got several different errors.
The Webservice is either not available or the myFacade is null or the there is a naming exception or there is something wrong with the classloading of the Bean.
But if you look at the following code-snippets below, perhaps you guys see something obvious?

I the app-structure:

foobar.ear
___foo.war
______web service
___bar-ejb.jar
______EJB


[code]

package my.facade.definition;

import javax.ejb.Local;

@Local
public interface MyFacade {

[/code]

[code]


package my.facade.service;

import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@RolesAllowed("my.MySystem")
public class MyFacadeBean implements MyFacade {

[/code]

[code]

package my.facade.webservice;

import javax.ejb.EJB;

@WebService(serviceName = "myFacadeService", portName = "myFacade", name = "....
public class MyFacadePortImpl implements MyFacadePort {

    /*
    java:global/my-app-7.0.0/my-facade-2.0.0/MyFacadeBean!my.facade.definition.MyFacade
    java:app/my-facade-2.0.0/MyFacadeBean!my.facade.definition.MyFacade
    java:module/MyFacadeBean!my.facade.definition.MyFacade
    java:global/my-app-7.0.0/my-facade-2.0.0/MyFacadeBean
    java:app/my-facade-2.0.0/MyFacadeBean
    java:module/MyFacadeBean
    */
    @EJB(lookup="java:app/my-facade-2.0.0/MyFacadeBean!my.facade.definition.MyFacade")
    private MyFacade myFacade;

    //@Inject
    //private MyFacade myFacade;

    //@EJB
    //private MyFacadeBean myFacade;
   
         
    public void doSome()
    {
        myFacade.doSomeEjbStuff()
         
[/code]


Best regards
Fredrik
Avatar billede arne_v Ekspert
08. december 2016 - 15:53 #1
@EJB
private MyFacadeBean myFacade

should work.

What error do you get?
Avatar billede fredand Forsker
09. december 2016 - 08:57 #2
Hello Arne!

When I tried:
@EJB
private MyFacadeBean myFacade;

Then I get:
Caused by: org.jboss.as.server.deployment.DeploymentUnitProcessingException: JBAS014544: No EJB found with interface of type 'my.facade.service.MyFacadeBean' for binding my.facade.webservice.MyFacadePortImpl/myFacade

Then I just tried "a wild stab in the dark" to add @Local to the bean itself and removed the interface like :
@Stateless
@Local
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@RolesAllowed("my.MySystem")
public class MyFacadeBean /*implements myFacade*/ {

@EJB
private MyFacadeBean myFacade;

But then I get:
Caused by:... JBAS014183: Bean class my.facade.service.MyFacadeBean specifies @Local annotation, but does not implement 1 interface

...so that does not seem to be the right way either.
Avatar billede fredand Forsker
09. december 2016 - 13:41 #3
Hello!

I manage a breaktrough.
I put @LocalBean in the bean MyFacadeBean and removed the interface.
Then this acctually worked:
    @EJB
    private MyFacadeBean myFacade.

I guess this is preferable since I get rid of some code. But using the interface way should have worked as well.

Best regards
Fredrik
Avatar billede arne_v Ekspert
09. december 2016 - 13:45 #4
Of course interface can be made to work.

Let me try and create an example.
Avatar billede arne_v Ekspert
11. december 2016 - 03:14 #5
I don't seem to have any problems.

Without interface:


package ejba;

import javax.ejb.LocalBean;
import javax.ejb.Stateless;

@LocalBean
@Stateless
public class TestBean {
    public String test() {
        return "It works!";
    }
}



package weba;

import java.io.IOException;

import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import ejba.TestBean;

@WebServlet(urlPatterns={"TestServlet", "/test"})
public class TestServlet extends HttpServlet {
    @EJB
    private TestBean tst;
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println(tst.test());
    }
}


With interface:


package ejbb;

import javax.ejb.Local;

@Local
public interface Test {
    public String test();
}



package ejbb;

import javax.ejb.Stateless;

@Stateless
public class TestBean implements Test {
    public String test() {
        return "It works!";
    }
}



package webb;

import java.io.IOException;

import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import ejbb.Test;

@WebServlet(urlPatterns={"TestServlet", "/test"})
public class TestServlet extends HttpServlet {
    @EJB
    private Test tst;
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println(tst.test());
    }
}


But maybe I missed something.
Avatar billede arne_v Ekspert
11. december 2016 - 03:14 #6
Note that usually @Local and @LocalBean are not really needed at all.

See example in:

http://www.vajhoej.dk/arne/articles/modernjee.html
Avatar billede fredand Forsker
12. december 2016 - 09:29 #7
Hello Arne!
Thanks for your great examples!
When I follow them I get them all to work.

I actually think that at least when of my errors was because I by mistake packed the file myfacade-interface-x.y.z.jar both at:
my-ear\lib
and
my-ear\myfacade-ws-x.y.z.war\WEB-INF\lib
When I just put it in my-ear\lib then it seemed to work.

Now I'm a bit confused which solution is best to use.
I'm told to always use interface as much as I can but since we never change the implementation of MyFacade like MyFacadeBean perhaps it is most practical to just do it like:

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@RolesAllowed("my.MySystem")
public class MyFacadeBean {

...and use it like:

@WebService(yada yada)
public class MyFacadePortImpl implements MyFacadePort {

@EJB
private MyFacadeBean myFacade;

One argument is of course that we get less code to maintain.

Best regards
Fredrik
Avatar billede arne_v Ekspert
12. december 2016 - 14:30 #8
The interface should only be one place and ear lib seems the right place.

(note that in JBoss wars can actually see the ejb jars within the same ear, so JBoss specific it could even be in the ejb jar)
Avatar billede arne_v Ekspert
12. december 2016 - 14:32 #9
I would use interface. It is not that much extra work and it does provide some extra flexibility if things change in the future.
Avatar billede fredand Forsker
13. december 2016 - 12:44 #10
Thanks for your comments amigo, it is always very valuable to get your opinion!
Best regards
Fredrik
Avatar billede fredand Forsker
06. november 2017 - 16:47 #11
Hello Arne!

I can not understand how I can have problem with this again.

I have also asked a question about this at:
https://stackoverflow.com/questions/47029058/how-to-use-local-ejb-annotation-between-war-and-jar-in-ear/47052122#47052122

My problem now is that I can not use @EJB and do local calls from a WAR to a JAR all inside a EAR in a JBoss 6.4.

Do you by any chance got a example with that situation?

Best regards
Fredrik
Avatar billede arne_v Ekspert
07. november 2017 - 03:11 #12
Hmmm.

Now I have read and experiemented a bit.

Last year I wrote:


(note that in JBoss wars can actually see the ejb jars within the same ear, so JBoss specific it could even be in the ejb jar)


Which I don't think is quite right.

It seems like:

JBoss AS 4.x - correct per documentation, correct per experiment
JBoss AS 7.x - wrong per documentation, wrong per experiment
WildFly 8.x - wrong per documentation, correct per experiment

So you should be able to make local EJB calls.

And you should be able to use injection, but you need to get classloaders right.

If you have the option to change server config then the trick at:

https://docs.jboss.org/author/display/AS71/Class+Loading+in+AS7


<subsystem xmlns="urn:jboss:domain:ee:1.0" >           
  <ear-subdeployments-isolated>false</ear-subdeployments-isolated>
</subsystem>


may simplify things.

Alternatively you can try move the interface to a separate jar file in ear lib.

I have not tried any of these.

Or you could simplify things a lot by just stuffing everything that are to be local into the war.
Avatar billede fredand Forsker
08. november 2017 - 07:19 #13
Hello Arne!

Just for your info, I'm working on your now lead's every spear time I got. I will be back asap.

Thanks a lot!!

Btw do you mean that "... wrong per documentation, wrong per experiment" means that you found some JBoss-documentation for that specific version that is in contradiction to what says in: https://docs.oracle.com/javaee/6/tutorial/doc/gipjf.html#girfl or in contradiction to your own documentation?
...And that you also tried it out and found that it did not work in that specific version?

I will try to experiment with the classloading more, but right now I did not get it to work. In my standalone.xml I found:

        <subsystem xmlns="urn:jboss:domain:ee:1.2">
            <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
            <jboss-descriptor-property-replacement>true</jboss-descriptor-property-replacement>
            <annotation-property-replacement>false</annotation-property-replacement>
        </subsystem>

I tried to add the ear-subdeployments-isolated-tag, but I got some errors at startup.

I also tried to add your tag, but in my JBoss EAP 6 it still did not work but no errors at start up.

<subsystem xmlns="urn:jboss:domain:ee:1.0" >           
  <ear-subdeployments-isolated>false</ear-subdeployments-isolated>
</subsystem>


I also found some some doc about jboss-deployment-structure.xml (hmm...seems lost the link) to me it looks like a alternative to the config in standalone.xml but I'm not sure.

<jboss-deployment-structure>
    <ear-subdeployments-isolated>false</ear-subdeployments-isolated>
</jboss-deployment-structure>

...but it did not do the trick either.

Right now I trying the idea to put the interface in EAR/lib...will get back to you asap!

Best regards amigo!
/Fredrik
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester