Hot questions for Using Enterprise JavaBeans in stateless

Question:

Can @Stateless class have different modifiers than public? In documentation I have only found constraints of constructor/methods visibility, but nothing interesting about class level access.


Answer:

According to ejb3-1 specification:

4.9.2 Session Bean Class

The following are the requirements for the session bean class:

• The class must be defined as public, must not be final, and must not be abstract. The class must be a top level class

Question:

Stateless EJB's should not have non-final static fields that are used to save state because this does not work in distributed apps with more that one JVM. But if we have a static final Map in EJB to save a few parameters about our distributed applications state is that ok and will the updates on the map be visible to applications running on separate JVMs?


Answer:

The whole point behind Stateless EJBS is that they are cheap because they don't need to be replicated in a distributed environment.

Therefore any state changes in your static final Map will not be replicated.

You would be better off using a distributed cache such as EhCache, Infinispan or even memcache for this purpose.

Question:

I'm heaving some trouble while learning ejb. All I want is write a simple app operatign on database. Here's my code:

Servlet - Main.java

package main;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
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;

@WebServlet(name = "Main", urlPatterns = {"/"})
public class Main extends HttpServlet {

@EJB
private NoteSB noteSB;

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    PrintWriter out = response.getWriter();
        List<Note> notes = noteSB.getNotes();
        for( int i=0,len=notes.size() ; i<len ; ++i ) {
            out.println(notes.get(i));
        }

}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
}


@Override
public String getServletInfo() {
    return "Short description";
}


}

Entity - Note.java

    /*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package main;

import java.io.Serializable;
import java.security.Timestamp;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "NOTES")
public class Note implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String note;
    private Timestamp date;

    public Note(){}

    public Note(String note, Timestamp date) {
        this.note = note;
        this.date = date;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof Note)) {
            return false;
        }
        Note other = (Note) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "Note["+ this.date +"]: " + this.note;
    }

}

Stateless Session bean - NoteSB.java

    package main;

import java.util.List;
import javax.annotation.PreDestroy;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
@LocalBean
public class NoteSB {


    @PersistenceContext(name = "jee-warPU")
    private EntityManager em;

    public void newNote(Note n) {
        em.persist(n);
    }

    public List<Note> getNotes() {
        return em.createNativeQuery("SELECT * FROM NOTES").getResultList();
    }

    @PreDestroy
    public void destroy() {
        em.close();
    }
}

persistance.xml

    <?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="jee-warPU" transaction-type="JTA">
    <jta-data-source>java:comp/DefaultDataSource</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="javax.persistence.schema-generation.database.action" value="create"/>
    </properties>
  </persistence-unit>
</persistence>

And here's my stack trace:

    Info:   file:/C:/Users/BB/Documents/NetBeansProjects/jee/jee-war/build/web/WEB-INF/classes/_jee-warPU logout successful
Info:   visiting unvisited references
Info:   visiting unvisited references
Info:   visiting unvisited references
Info:   visiting unvisited references
Info:   visiting unvisited references
Info:   EclipseLink, version: Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd
Info:   file:/C:/Users/BB/Documents/NetBeansProjects/jee/jee-war/build/web/WEB-INF/classes/_jee-warPU login successful
Info:   Portable JNDI names for EJB NoteSB: [java:global/jee-war/NoteSB, java:global/jee-war/NoteSB!main.NoteSB]
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] org.glassfish.sse.impl.ServerSentEventCdiExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>, BeanManager) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] public org.glassfish.jms.injection.JMSCDIExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
Info:   Loading application [jee-war] at [/jee-war]
Info:   jee-war was successfully deployed in 783 milliseconds.
Info:   WebModule[null] ServletContext.log():Marking servlet Main as unavailable
Warning:   StandardWrapperValve[Main]: Allocate exception for servlet Main
java.lang.IllegalArgumentException: Can not set main.NoteSB field main.Main.noteSB to main.Main
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:75)
    at java.lang.reflect.Field.set(Field.java:758)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:688)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:507)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:141)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:127)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:347)
    at com.sun.enterprise.web.WebContainer.createServletInstance(WebContainer.java:991)
    at com.sun.enterprise.web.WebModule.createServletInstance(WebModule.java:2130)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1404)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:1211)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:237)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:415)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:282)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
    at java.lang.Thread.run(Thread.java:745)

I will appreciate any help! I've tried many tutorials and options and still can't figure out what it is all about. Digging the stack trace is just getting me crazy, I partially understand the errors but don't know what to do, please help :)


Answer:

You're missing visible accessor methods for your noteSB field. Add the following getter and setter methods to your Main class:

public class Main extends HttpServlet {

    // all your current code here

    public NoteSB getNoteSB() {
        return this.noteSB;
    }

    public void setNoteSB(NoteSB noteSB) {
        this.noteSB = noteSB;
    }
}

Refer to the JavaBean specification. Specifically this passage:

7.1 Accessor methods

Properties are always accessed via method calls on their owning object. For readable properties there will be a getter method to read the property value. For writable properties there will be a setter method to allow the property value to be updated. Thus even when a script writer types in something such as "b.Label = foo" there is still a method call into the target object to set the property, and the target object has full programmatic control.

So properties need not just be simple data fields, they can actually be computed values. Updates may have various programmatic side effects. For example, changing a bean’s background color property might also cause the bean to be repainted with the new color.

For simple properties the accessor type signatures are:

void setFoo(PropertyType value); // simple setter
PropertyType getFoo(); // simple getter

Question:

I'm looking for an elegant solutions to the old problem of loading and caching static, shared data at application startup (with an infinite lifetime).

My old way was a Spring Singleton Bean, but I'm trying now to achieve it with JAVA EE 6 (JPA2, EJB3.1, CDI).

I have an @Entity, and an @Stateless EJB lo load the entity from database. My thought was to add a @Singleton EJB to cache the data; I also decided to keep the original EJB separated, to prevent violating SRP (and because in the future it might be used bypassing the cache, by other actors).

Please take a look at this simplified Proof Of Concept:

Entity

@NamedQuery(name="Room.findAll", query="SELECT r FROM Room r")
@Entity
public class Room {

    @Id 
    private Integer id;          // GETTER, SETTER
    private String description;  // GETTER, SETTER
}

Loader

@Stateless
public class Rooms {

    @PersistenceContext
    EntityManager em;

    public List<Room> findAll() {
        return em.createNamedQuery("Room.findAll",Room.class).getResultList();
    }
}

Cacher

@Singleton
public class RoomsCached {

    @EJB
    Rooms rooms;

    private List<Room> cachedRooms; // GETTER

    @PostConstruct
    public void initCache(){
        this.cachedRooms = Collections.unmodifiableList(rooms.findAll());
    }        
}

Can you see big problems, conceptual errors or something in this example ?

My main concerns were

  1. If both were @Singleton (mehh), I could have added @DependsOn("Rooms") on the cacher bean, to ensure Rooms is already loaded before being used, but with @Singleton and @Stateless I can't... will @Stateless bean always be loaded before CDI injects it into @Singleton ?

  2. @Singleton calling @Stateless seems weird (I've seen examples of the opposite); should I change design by putting the @Singleton instance inside the @Stateless EJB ?

  3. Is it right to load and cache in the @PostConstruct method ?


Answer:

Well, I've made some tests, and I've also tried the @Decorator way. This still seems to be the best one.

@Entity bean and @Stateless bean are the same of the question, while I've changed the @Singleton bean as follows, also adding the classic timed cache:

@Singleton
public class RoomsCached {

    @Inject
    Rooms rooms;

    private List<Room> cachedRooms; 
    private long timeout = 86400000L; // reload once a day
    private long lastUpdate;    


    public List<Room> getCachedRooms() {
        initCache();
        return cachedRooms;
    }

    public void initCache() {
        if (cachedRooms == null || expired()) {
            cachedRooms = Collections.unmodifiableList(rooms.findAll());
            lastUpdate  = System.currentTimeMillis();
        }
    }        

    private boolean expired() { 
        return System.currentTimeMillis() > lastUpdate + timeout; 
    }

}

No need to @PostConstruct, nor to @EJB, no sync issues with the underlying, @inject-ed @Stateless bean.

It's working great.

Question:

I have an EJB Stateless Bean that is executed automatically by an Scheduler inside Websphere. My EJB is installed in Websphere. Inside my EJB I would like to make an http request to a webservice exposed by other application (inside de same Server). I tried just using relative path because that is how I usually make requests between applications, but inside my bean I don't know how to get the host name and port to build the URL.

I managed to get the host (ip) by doing this:

InetAddress.getLocalHost().toString();

But I also require the port number. The question is: how to get the host and port number of the application server (Websphere) where my EJB application is installed? Is this possible?

This code is how I try to make the request, but this does not work because I need the full path:

URL url = new URL("/MyOtherAppName/myservice");         
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

connection.setRequestProperty("Content-Length", 
    Integer.toString(urlParameters.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");  

connection.setUseCaches(false);
connection.setDoOutput(true);

-edit 1 ----

I think the approach of user Gas is nice, and makes my application easier to configure.

I followed this guide to implement the URL Provider approach:

URL Provider Websphere


Answer:

I'd suggest different approach, rather than getting server host and port use the URL resource and then get it in the EJB. It will be more portable across servers and also more flexible in case you ever move your service somewhere else.

See Using URL resources within an application

Define URL via console in app server, and use @Resource annotation in your EJB like this:

@Resource(name="serviceURL", lookup="url/myurl")
URL myURL;

Question:

I want to make some file operations (copy) in stateless EJB Method. I know about not recommndig to do it. But it could be possible for some special EJB implementation. What is the best thing for Wildfly ?

EDIT Some disturbing old links:

"Sun blueprint: EJB Restrictions"

EJB Bad Practices: Use of Java I/O

Stackoverflow


Answer:

What is the best thing for Wildfly ?

Just doing the file operation (seriously). It's not as-if there's a security manager installed to prevent you from doing this.

And a stateless EJB is not different from many other types of methods in beans in Java EE. It's not the case, as some people think, that it's not allowed in EJB methods but is allowed in CDI bean methods. This is simply not the case.

There's some old information out there, where the spec said that "EJB was not allowed to". But what was actually meant is that Java EE was not allowed to. At the time EJB was seen as equivalent to Java EE, so that's the origin of this wide spread confusion.

Later this myth was starting a life of its own where people dreamed up scenarios where it was supposedly allowed to do IO in Servlets, but not from an EJB, so they designed all kinds of crazy architectures to delegate IO (or threading, another favorite) from an EJB to a Servlet. Absolutely ludicrous!

The restriction (as mentioned above, intended for the whole of Java EE, not just EJB) was also put in too eagerly. There's simply no reason to absolutely forbid it.

Some of the answers that you quote are more retroactive reasons. People just make up reasons for a rule to somehow justify their world, even though the reason and the rule don't match.

For this reason, the rule has been removed from the EJB spec.

That's right, in the current EJB spec you will not longer find that it's forbidden to use IO from an EJB (which, again, never meant to say "EJB", but should be read as "Java EE").

See:

Of course, as with many things, you may or may not have to be cautious when using IO, but this is completely unrelated to Java EE or EJB and holds for almost any application, and is more dependent on the kind of IO, the kind of application you're coding and your situation.

Two small extreme examples:

Your very own personal Java EE application of which you are the only developer that you installed at home on your raspberry pi and that reads a small configuration file at startup from an external location -> pretty much always okay.

Large clustered enterprise application being developed by many different teams, integrated separately, deployed separately, highly transactional that wants to write temporary data to a filesystem but that has to be cleanedup again when the transaction ends -> likely not such a good idea.

Between those two that are literally an infinite amount of variations. We had for example a larger enterprise application that did IO to an external folder from a Singleton in a very controlled and specific way. The app served millions of users under intense load and there was never a problem with the IO. So even "enterprise" and "transactional" do not necessarily have to mean "no IO". It really depends.

Question:

I'm following an EJB cookbook, from packt, with the following code:

package packt;

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

//@Stateless
@LocalBean
@Stateless(mappedName="salutationBean")
public class Salutation {
    public String getFormalSalutation(String name) {
        return "Dear " + name;
    }
    public String getInformalSalutation(String name) {
        return "Hi " + name;
    }
}

How do i access this bean from a class which doesn't extend HttpServlet? The servlet itself works fine:

package servlet;

import java.io.IOException;
import java.io.PrintWriter;
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 packt.Salutation;

@WebServlet(urlPatterns = {"/SalutationServlet"})
public class SalutationServlet extends HttpServlet {

    @EJB
    private Salutation salutation;

    protected void processRequest(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet SalutationServlet</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>"
                    + salutation.getFormalSalutation("Sherlock Holmes")
                    + "</h1>");
            out.println("</body>");
            out.println("</html>");
        } finally {
            out.flush();
            out.close();
        }
    }

    @Override
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
}

and is viewable from the designated URL:

thufir@dur:~$ 
thufir@dur:~$ lynx http://localhost:8080/SalutationApplication-war/SalutationServlet -dump
                              Dear Sherlock Holmes


thufir@dur:~$ 

The current structure:

thufir@dur:~/NetBeansProjects$ 
thufir@dur:~/NetBeansProjects$ tree SalutationApplication/
SalutationApplication/
├── build.xml
├── nbproject
│   ├── ant-deploy.xml
│   ├── build-impl.xml
│   ├── genfiles.properties
│   ├── private
│   │   └── private.properties
│   ├── project.properties
│   └── project.xml
├── SalutationApplication-ejb
│   ├── build.xml
│   ├── nbproject
│   │   ├── ant-deploy.xml
│   │   ├── build-impl.xml
│   │   ├── genfiles.properties
│   │   ├── private
│   │   │   └── private.properties
│   │   ├── project.properties
│   │   └── project.xml
│   └── src
│       ├── conf
│       │   └── MANIFEST.MF
│       └── java
│           └── packt
│               └── Salutation.java
├── SalutationApplication-war
│   ├── build.xml
│   ├── nbproject
│   │   ├── ant-deploy.xml
│   │   ├── build-impl.xml
│   │   ├── genfiles.properties
│   │   ├── private
│   │   │   └── private.properties
│   │   ├── project.properties
│   │   └── project.xml
│   ├── src
│   │   ├── conf
│   │   │   └── MANIFEST.MF
│   │   └── java
│   │       └── servlet
│   │           └── SalutationServlet.java
│   └── web
│       ├── index.html
│       └── WEB-INF
└── src
    └── conf
        └── MANIFEST.MF

20 directories, 27 files
thufir@dur:~/NetBeansProjects$ 

Right now it's fine that it's only a local bean, but ultimately I would like the Salutation.java bean to be accessible remotely. I have a passing familiarity with EJB from Head First EJB, but that's quite old.


Answer:

(This answer relates the my comment above.)

In objects that are not managed automatically by the container, you can initialize a manual injection by obtaining a reference to the BeanManager and let the CDI container do all the work for you. This works with everything that you can also inject into managed beans, but you don't have to do the complicated JNDI lookup.

public class CDIUtils {

    public static BeanManager beanManager() {
        try {
            return (BeanManager) new InitialContext().lookup("java:comp/BeanManager");
        } catch (NamingException e) {
            throw new IllegalStateException("Unable to obtain CDI BeanManager", e);
        }
    }

    public static void makeManagedStatic(Object obj) {
        BeanManager bm = beanManager();
        makeManaged(obj, bm);
    }

    public static void makeManaged(Object obj, BeanManager beanManager) {
        Class objClass = (Class) obj.getClass();
        AnnotatedType annotatedType = beanManager.createAnnotatedType(objClass);
        InjectionTarget injectionTarget = beanManager.createInjectionTarget(annotatedType);
        CreationalContext context = beanManager.createCreationalContext(null);
        injectionTarget.inject(obj, context);
    }

}

Suppose this was your client:

public class MyClient {
    @EJB private MyEJB myEJB;
    public void run() {
        if (myEJB == null)
            CDIUtils.makeManagedStatic(this);
        myEJB.someMethod();
    }
}

You can also simply make them managed at creation, this spares the test for null:

MyClient client = new MyClient();
CDIUtils.makeManagedStatic(client);
client.run(); // etc

Question:

I have some code in a bean that monitors a connection handle:

@Stateless
public class MyClass { 
    private CloseableHttpAsyncClient deviceHandle = null;
    @Schedule(second="*/30", minute="*", hour="*", persistent=false)
    void checkConnection()
    {
        if (deviceHandle != null) {
            if (deviceHandle.isRunning()) {
                // Ping connection
            }
            else {
                deviceHandle = reconnectToDevice();
            }
        }
    }

    public void initialise() {
        deviceHandle = connectToDevice();
    }
}

According to the EJB 3.1 specs @Schedule may be used only on @Stateless beans, so of course my code fails because I get a different bean on the timer ticks with a null deviceHandle.

Therefore, my question is what is the best practise for this requirement - where should I stash my handle? @Inject a @Singleton? @Inject an @ApplicationScoped bean? @Inject the bean from my ServletContextListener and store the state there (I do that with another truly @Stateless timer tick)?


Answer:

The most obvious solution is to turn your MyClass itself into a @Singleton.

The EJB 3.1 spec does allow the use of @Schedule in singletons. Section 18.2.3 of the spec even contains the following example:

@Singleton
public class CacheBean {
    Cache cache;
    // Setup an automatic timer to refresh
    // the Singleton instance cache every 10 minutes
    @Schedule(minute="*/10", hour="*", persistent=false)
    public void refresh() {
    // ...
    }
}

Question:

I am not so experienced in EJBs, especially EJB 3.0 and thus, I faced out with a question I would like to resolve. A similar issue I have found here, but the suggested solution did not help.

I have a remote stateless EJB with its business methods declared in interface and the bean which implements those methods has also other methods which are not declared in interface.

As an example here is the business interface:

public interface BusinessLogic {
    Object create();
    void delete(Object x);
}

A BusinessLogicBean which implements the business logic:

@Stateless
@Remote(BusinessLogic.class)
public class BusinessLogicBean implements BusinessLogic {

    /** implemented method */
    public Object create() {
        Object x = new SomeDBMappedObject();
        // create an object in DB and return wrapper class
        ...
        return x;
    }

    /** implemented method */
    public void delete(Object x) {
        // deleting object from DB
        ...
    }

    /** The method that performs some extra logic */
    public void aMethod() {
        // do extra logic
    }
}

I need to write unit tests for that EJB using Arquillian framework including for the bean methods which are not declared in the business interface.

Example:

@RunWith(Arquillian.class)
public class BusinessLogicTest {

    /** will be injected during the test run */
    @EJB
    private BusinessLogic businessLogic;

    @Deployment
    public static Archive createDeployment() {
        WebArchive war = ShrinkWrap.create(WebArchive.class, "test.war")
                // add needed libraries and classes
                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");

        return war;
    }

    @Test
    public void aMethodTest() {
        businessLogic.aMethod();

        // Write appropriate assertions
    }
}
My questions are:
  • how can I call aMethod() in my test? I cannot call it like businessLogic.aMethod();, since it will result in a compilation error. I cannot call it like ((BusinessLogicBean) businessLogic).aMethod();, as it will result in a ClassCastException since the actual object is a com.sun.proxy.$ProxyXXX type. or
  • Is there a way to inject BusinessLogicBean object directly instead of BusinessLogic?

Answer:

You can annotate BusinessLogicBean with @javax.ejb.LocalBean

@Stateless
@LocalBean
@Remote(BusinessLogic.class)
public class BusinessLogicBean implements BusinessLogic {
...
}

and inject it by its class name:

@EJB BusinessLogicBean businessLogicBean;

See also:

  • Docs
  • A useful related question

Question:

scenario: EjbA and EjbB are both remote stateless session beans.

@Stateless
public class EjbA
{
  @EJB
  private EjbB b;

  public void foo(){
    b.method1();
    b.method1();
    b.method2();
  }
}

Is it correct that any of these method calls on b can happen on a different node/VM in a clustered environment?

Even the calls to method1?

I mean if some client calls method foo, can it happen that in the this transaction method1 is called on node1 and the next call to method1, during the same invocation of foo(), goes to an Ejb instance on node2?

Interpreting the following quote from "Enterprise JavaBeans 3.1":

"... each invocation upon a SLSB proxy operates independently from those both before and after. In fact, its underlying bean instances may be swapped interchangeably between requests."

I would say yes.

Is there any way to ensure that these calls happen to the same stateless session bean instance on the same node/VM?

If I am right with my first assumption, it should not be possible.

E.g. using a singleton only ensures that an Ejb is unique per VM. So in a clustered environment it doesn't give me this guarentee.


Answer:

Is it correct that any of these method calls on b can happen on a different node/VM in a clustered environment?

Yes, method calls can be remote - so long as you have properly setup the remote interface on EjbB

Even the calls to method1?

I mean if some client calls method foo, can it happen that in the this transaction method1 is called on node1 and the next call to method1, during the same invocation of foo(), goes to an Ejb instance on node2?

Interpreting the following quote from "Enterprise JavaBeans 3.1":

"... each invocation upon a SLSB proxy operates independently from those both before and after. In fact, its underlying bean instances may be swapped interchangeably between requests."

I would say yes.

I 100% agree with your assessment. In fact, container implementors are free to create and destroy Stateless Session Beans on each method invocation -- they are independent from eachother.

Is there any way to ensure that these calls happen to the same stateless session bean instance

You'd have to make the EJB a @Singleton. That way you ensure that it's only created once per EJB Container Classloader

on the same node/VM?

Yes you can make sure all calls are local - do not define a remote interface. By default all EJBs only expose local interfaces; meaning if you don't do any extra work - you're always calling local EJBs.

There's no reliable way to "force" independent method calls to be handled by the same Stateless Bean. If you're trying to maintain a "conversational state" between EjbA and EjbB then this is what the Stateful Session bean is for. With a Stateful Session Bean, the method invocations are not only guaranteed to be handled by the the same bean but EjbB will be able to remember state between the method calls from EjbA. In this setup EjbB would be completely dedicated to the specific instance of EjbA and would not serve any other clients until EjbA ends the session - by being destroyed for example.

Question:

so i am new to testing with mockito and i have looked up a couple of tutorials but i'm pretty slow to understanding. I have an endpoint that is backed with an EJB. i want to test the methods in the EJB. I've tried so many options, apparently i get a nullpointer exception. (i know what a nullpointer exception is). the mocked entity manager does not persist the objects. so it gives me a null pointer exception when i try to perform any operation on an empty list. please anyone can show me how to go about this or point me to any detailed article or tutorial i could read to facilitate my learning. thanks Guys.

this is my ejb.

@Stateless
public class CustomerHandler {

  @PersistenceContext
  private EntityManager em;

  public Response borrowMovie(List<RequestMovieDto> borrow) {
    borrow.forEach(movies -> {
        final Movie movie = findMovieByName(movies.getName());
        movie.setAvailableCopies((movie.getAvailableCopies()) - movies.getAmount());
        em.merge(movie);
    });

    return Response.ok(borrow).build();
  }

  public Movie findMovieByName(String name) {
    return em.createQuery("SELECT m FROM Movie m "
        + "WHERE m.name = :name", Movie.class)
        .setParameter("name", name)
        .getSingleResult();
  }
} 

and this is my test class

@RunWith(MockitoJUnitRunner.class)
public class MovieHandlerTest {

  @Mock
  EntityManager manager;

  private List<RequestMovieDto> request;

  @InjectMocks
  CustomerHandler handler;

  @Before
  public void setUp() {
    final Movie first = new Movie();
    first.setName("MISSION IMPOSSIBLE");
    first.setAvailableCopies(10);
    first.setIsbn("ABC788900");

    manager.persist(first);

    final Movie second = new Movie();
    first.setName("JAMES BOND");
    first.setAvailableCopies(10);
    first.setIsbn("ABC788999");

    manager.persist(second);

    final Movie last = new Movie();
    first.setName("HARRY POTTER");
    first.setAvailableCopies(10);
    first.setIsbn("ABC7882000");

    manager.persist(last);

  }

  @Test
  public void borrowMovie() {
    RequestMovieDto first = new RequestMovieDto();
    first.setName("MISSION IMPOSSIBLE");
    first.setAmount(2);

    RequestMovieDto second = new RequestMovieDto();
    second.setName("JAMES BOND");
    second.setAmount(1);

    request = Arrays.asList(first, second);
     final var response = handler.borrowMovie(request);

    assertEquals(Response.Status.OK, response.getStatusInfo().toEnum());
  }
}

Answer:

To avoid the NullPointerException, you can try adding the following code in the MovieHandlerTest class:

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;

[..]

@Mock
EntityManager manager;

@Mock
TypedQuery<Movie> query;

[..]

@Before
public void setUp() {
    final Movie first = new Movie();
    first.setName("MISSION IMPOSSIBLE");
    first.setAvailableCopies(10);
    first.setIsbn("ABC788900");

    final Movie second = new Movie();
    first.setName("JAMES BOND");
    first.setAvailableCopies(10);
    first.setIsbn("ABC788999");

    final Movie last = new Movie();
    first.setName("HARRY POTTER");
    first.setAvailableCopies(10);
    first.setIsbn("ABC7882000");

    when(manager.createQuery(any(String.class), eq(Movie.class))).thenReturn(query);
    when(query.setParameter(any(String.class), any(String.class))).thenReturn(query);
    when(query.getSingleResult()).thenReturn(first, second, last);
}

But another problem arises with "Response.ok(borrow).build()"

You have 3 solutions:

  1. Refactor the code to introduce a class that executes the borrowing workflow and returns a model, then unit test this class
  2. Add a JAX-RS implementation with a test scope, such as Jersey
  3. Since you can't mock static methods with Mockito alone, you can try adding another testing library, such as PowerMockito, and mock the Reponse static method calls.

For solution 2, you can add the following maven dependency:

    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-server</artifactId>
        <version>2.13</version>
        <scope>test</scope>
    </dependency>

Question:

I'm kind of a newbie in EJBs,but I've been given an EJB tier to improve. This tier consists of an EJB wich exposes the operations available:

@Stateless(name = "myejb")
public class Facade implements FacadeRemote
{
    @EJB
    private EntityAHomeLocal entityAHome;

    @EJB
    private EntityBHomeLocal entityBHome;

// methods signatures and implementations
}

As you can see this EJB use other local EJBs that manage operations on entities.

@Stateless
public class EntityAHome implements EntityAHomeLocal
{
    @PersistenceContext(name="myUnit")
    private EntityManager manager;


    // methods signatures and implementations
}

I'm having hard time to fully understand the architecture of this tier.

  • Is this kind of architrcture common ?
  • Are local stateless EJB managed throught a pool of instances just like remote stateless EJBs ?
  • Would it still work even if entityAHome and entityBHome were remote EJBs ?

Answer:

Strictly speaking, the spec only says stateless beans are "typically" pooled (section 4.3.10.2), so the behaviour for local beans is vendor-specific, but in practice I believe all the major vendors do (for example).

Local and remote interfaces are almost entirely interchangeable, but with extra deployment restrictions (i.e. they must be deployed locally, of course), and some calls to local interfaces use pass-by-reference semantics, whereas remote interfaces always use pass-by-value (link).

I can't see anything that would stop that code working with remote interfaces, although I think some of the naming is confusing - a session bean (@Stateless) is different from an entity, and in EJB terminology "home" refers to a kind of factory class, which I don't think is your intention here (?). Also, be aware that switching to @Remote can add a performance overhead, as the second link notes.

Question:

I have a class of staleless EJB (not singleton!). I need one method to be called (load configuration) only once when first bean of this class is created. @PostConstruct solves half of my problem but it's executed for every bean. What is the most elegant way to solve such problem?


Answer:

I see tow options:

  • Consider using a singleton object encapsulating the configuration data of your file and add a reference to it in your EJB.

  • consider a creational design patterns. I think that the prototype pattern should fit your need but you may find other alternatives. Check this for details: http://en.wikipedia.org/wiki/Software_design_pattern.

Question:

I have the following setup:

@Singleton
@Startup
@DependsOn(value="DataSourceHandler")
public class TimerTask {

    @EJB(name = "DataSourceHandler")
    DataSourceHandler dataSourceHandler;
}

@Stateless(name = "DataSourceHandler")
public class DataSourceHandler {
    ... database operations
}

The timertask runs once every 30 minutes and performs database operations with the help of the DataSourceHandler EJB.

The problem here is that I'm unable to inject the EJB into the Singleton Timertask, because a singleton can only depend on other singletons. The solutions proposed in other questions don't work for me however:

  • I can't make the DataSourceHandler a Singleton because it is also used in other parts of the application and not multithreading-save.
  • I can't remove the Singleton from the TimerTask because it is required for the @Startup annotation

How can I inject a stateless into a singleton?


Answer:

You do not need a dependsOn annoatation here. @dependson is used for the below case:

Used to express an initialization dependency between singleton components.

Since DataSourceHandler is an EJB, it will be instantiated by the container at the moment your singleton injects this EJB.

Question:

I've found this @Stateless annotation in some code like:

public Interface A

@Stateless
public abstract class B implements A

public class C extends B

public class D extends B

But Intellij is then saying B shouldn't be declared as abstract. Is Intellij right here and the Stateless is not actually propagated to the classes extending B and I'd have to declare them as Stateless or C, D are properly set as Stateless?


Answer:

You need to add Stateless in all subclasses too.

Take a look at this: Inheriting class annotations

Only the annotations annotated with @Inherited are propagated https://www.logicbig.com/tutorials/core-java-tutorial/annotations/inherited-meta-annotation.html

Question:

I am wondering why do we use stateless annotation when using TransactionAttributeType, like so:

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
@Stateless
public class Controller {

Any help is appreciated, thanks!


Answer:

@Stateless determines the type of bean (one that does not maintain a conversational state with the client). @TransactionAttribute determines the way to handle transactions. In your example the bean won't hold client-specific state after the end of invocation. But when you choose REQUIRES_NEW it will always create a new transaction for each method invocation (in contrast to default REQUIRED when existing transaction can be used and if it doesn't exist it will be created by container).

Question:

I have a stateless EJB version 3.0 running that supposed to fire once every 30 seconds. My problem is that after I got it running, no matter what I do, it will always run with 4 active timers (verified in my WebLogic console) that go off about every 2 seconds or so.

Sadly, I can't be super specific with my code, but here is what I have:

  • A create timer method that I'm calling at the beginning of my program. Here is a timerService.createTimer call. This really doesn't do anything because the timers are still being created without this being called. Why?
  • A @postConstruct method that is just printing something out for testing. It's being called like it should.
  • A @Timeout method that is being called WAY more than it should because of the multiple timers. This is where my business logic is.
  • In my weblogic-ejb-jar.xml I have the max-beans-in-free-pool set to 1

Any suggestions would be greatly appreciated. I think I don't have a full understanding of what's going on, but I can't find anything helpful for this.


Answer:

In EJB 3.0 all timers are persistent. In other words they survive server restarts.

If you create an interval timer it will run until you cancel it. Stopping the server will not cancel it. Many implementations have been known to try and catch up again when the server is restarted.

Your existing code is creating yet another timer when you restart it.

Consider adding the following to an @PostConstruct method in the EJB that services the Timer:

 @Resource
 private TimerService timerService;

 @PostConstruct
 void startup() {
     ...
     for (Timer timer: timerService.getTimers()) {
         timer.cancel();
     }
     ...
 }

This should clean things up for you.

Question:

I am relatively new to Java EE and I am a bit confused as to how I access a stateless Java Bean from my Enterprise Application Client.

My intention is for my enterprise bean, CarReposityImpl, to handle database access and entity management for an entity class called Car.

My CarRepositoryImpl looks like:

@Stateless
public class CarRepositoryImpl implements CarRepository
{   
    @PersistenceContext(unitName = "FIT5042AssignmentEJBPU")
    private EntityManager entityManager;

    @Override
    public void addCar(Car car)
    {
        entityManager.persist(car);
    }

    @Override
    public Car searchByVIN(String vin) throws Exception
    {
        Car car = entityManager.find(Car.class, vin);
        return car;
    }

    @Override
    public List<Car> getAllCars() throws Exception 
    {        
        return entityManager.createNamedQuery(Car.GET_ALL_QUERY_NAME).getResultList();
    }

    @Override
    public void removeCar(String vin) throws Exception 
    {          
        Car car = searchByVIN(vin);

        if (car != null) 
        {
            entityManager.remove(car);
        }
    }    

    @Override
    public void editCar(Car car) throws Exception 
    {      
        entityManager.merge(car);
    }    
}

It implements the interface CarRepository that looks like:

@Remote
public interface CarRepository 
{
    public void addCar(Car car);
    public Car searchByVIN(String vin) throws Exception;
    public List<Car> getAllCars() throws Exception;
    public void removeCar(String vin) throws Exception;
    public void editCar(Car car) throws Exception;
}

The entity class Car looks like:

@Entity
@Table(name = "CAR")
@NamedQueries({@NamedQuery(name = Car.GET_ALL_QUERY_NAME, query = "SELECT c FROM Car AS c")})
public class Car implements Serializable
{
    public static final String GET_ALL_QUERY_NAME = "Car.getAll";
    //private Sale sale;
    String modelNo, VIN, model, make, type, thumbnail, description, prevURL;

    public Car() {
    }

    public Car(String varModelNo, String varVIN, String varModel, String varMake, String varType, String varThumb, String varDesc, String varPrevURL)
    {
        modelNo = varModelNo;
        VIN = varVIN;
        model = varModel;
        make = varMake;
        type = varType;
        thumbnail = varThumb;
        description = varDesc;
        prevURL = varPrevURL;
    }

    public void setModelNo(String varModNo){modelNo = varModNo;}
    public void setVIN(String varVIN){VIN = varVIN;}
    public void setModel(String varMod){model = varMod;}
    public void setMake(String varMake){make = varMake;}
    public void setType(String varType){type = varType;}
    public void setThumbnail(String varThumb){thumbnail = varThumb;}
    public void setDesc(String varDesc){description = varDesc;}
    public void setPrevURL(String varPrev){prevURL = varPrev;}

    @Column(name = "modelNo")
    public String getModelNo(){return modelNo;}

    @Id
    @Column(name = "VIN")
    public String getVIN(){return VIN;}

    @Column(name = "model")
    public String getModel(){return model;}

    @Column(name = "make")
    public String getMake(){return make;}

    @Column(name = "type")
    public String getType(){return type;}

    @Column(name = "thumbnail")
    public String getThumbnail(){return thumbnail;}

    @Column(name = "description")
    public String getDesc(){return description;}

    @Column(name = "prevURL")
    public String getPrevURL(){return prevURL;}
}

From my understanding I should be able to add this line:

public class CarSales 
{
    @EJB
    private static CarRepository carRepo;

to the class in my Enterprise Application Client that handles my business logic and then I should be able to it to call the methods inside my CarRepositoyImpl bean to access the my database. I am pretty sure I am not supposed to instantiate the carRepo object like a normal object because the EJB container is supposed to handle that.

Essentially I want to be able to use my stateless bean in my Application client like this:

List<Car> cars = carRepo.getAllCars();

but when I do it throws a null pointer exception and I have no idea why.

My application client class as it currently stands, it is mostly incomplete:

public class CarSales 
{
    @EJB
    private static CarRepository carRepo;

    private final MainScreen main;

    public CarSales()
    {
        main = new MainScreen();
        addCarActionListeners();
    }

    public void run()
    {
        displayAllCars();
    }

    private void displayAllCars()
    {
        main.getCarScreen().clearTable();

        try
        {
            List<Car> cars = carRepo.getAllCars();

            for(Car car : cars)
            {//"VIN", "Model Number", "Model Name", "Make", "Thumbnail", "Description", "URL"
                String[] data = new String[7];
                data[0] = car.getVIN();
                data[1] = car.getModelNo();
                data[2] = car.getModel();
                data[3] = car.getMake();
                data[4] = car.getThumbnail();
                data[5] = car.getDesc();
                data[6] = car.getPrevURL();
                main.getCarScreen().getModel().addRow(data);
            }
        }
        catch(Exception ex)
        {
            main.getCarScreen().outputAddError(ex.getMessage());
            System.out.println("failed");
            ex.printStackTrace();
        }
    }

    private void addCarActionListeners()
    {//CLOSE
        main.getCarScreen().getClose().addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                main.closeWindow();
            }
        });

        main.getCarScreen().getAdd().addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                Car car = new Car(main.getCarScreen().getModelNo(), 
                            main.getCarScreen().getVin(),
                            main.getCarScreen().getModelName(),
                            main.getCarScreen().gerMake(),
                            main.getCarScreen().getType(),
                            main.getCarScreen().getThumb(),
                            main.getCarScreen().getDesc(),
                            main.getCarScreen().getUrl());
                try
                {
                    System.out.println("try");
                    carRepo.addCar(car);
                    displayAllCars();
                }
                catch(Exception ex)
                {
                    System.out.println("catch");
                    //main.getCarScreen().outputAddError(ex.getMessage());
                    System.out.println(ex.getMessage());
                }
            }
        });
    }
}

Stack trace of my error:

java.lang.NullPointerException
at CarSales.CarSales.displayAllCars(CarSales.java:45)
at CarSales.CarSales.run(CarSales.java:36)
at CarSales.Main.main(Main.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.glassfish.appclient.client.acc.AppClientContainer.launch(AppClientContainer.java:446)
at org.glassfish.appclient.client.AppClientFacade.main(AppClientFacade.java:166)

Line 45 is:

List<Car> cars = carRepo.getAllCars();

Made some suggested changes to my CarSales Class:

public class CarSales 
{
    @EJB
    private CarRepository carRepo;

    private final MainScreen main;

    public CarSales()
    {
        main = new MainScreen();
    }

    @PostConstruct
    public void init() 
    {
        addCarActionListeners();
    }

    public void run()
    {
        displayAllCars();
    }

My main function that calls run:

public class Main 
{
    public static void main(String[] args) 
    {
        CarSales sys = new CarSales();
        sys.run();
    }
}

Answer:

If you create an object yourself, then the container has no chance to perform injection. In the client container, effectively only the main class is eligible for injection. Try:

public class Main 
{
    @EJB
    private static CarRepository carRepo;

    public static void main(String[] args) 
    {
        CarSales sys = new CarSales(carRepo);
        sys.run();
    }
}

public class CarSales 
{
    private final CarRepository carRepo;
    private final MainScreen main;

    public CarSales(CarRepository carRepo)
    {
        this.carRepo = carRepo;
        main = new MainScreen();
    }

Alternatively, you can declare the reference in your main class, and then look up the EJB reference from anywhere in the client application:

@EJB(name="ejb/carRepo", beanInterface=CarRepository.clas)
public class Main 
{
    public static void main(String[] args)

...
CarRepository carRepo = (CarRepository)new InitialContext().lookup("java:comp/env/ejb/carRepo");

Question:

I did not understand about stateless session beans. The documentation says that the instances variables may contain client specific state and then says that when the method is finished the state should not be retained.

Lets say there is a method X and two clients called at the same time. The method X saves the client name in an instance variable. I see that there will be an issue when multiple threads call the same method simultaneously.

T1 accesses X and X sets the client name in a instance variable and sleeps. T2 accesses X and X sets the client name in a instance variable and sleeps. T1 resumes and X now sees T2's data.

Isn't this a problem? Or, does the container create a new instance for every client and destroys the ejb once the call is returned?

Secondly-- Clients may, however, change the state of instance variables in pooled stateless beans, and this state is held over to the next invocation of the pooled stateless bean.

Does this means that the same client can see its data across different method invocations? Or does it mean different client see each others data across method invocations?


Answer:

Isn't this a problem? No it is not, the second client will not get a reference to the same bean instance until the first one finishes its request (it has nothing to do with thread scheduling mechanism, it works on per request basis).

Does this means that the same client can see its data across different method invocations? Or does it mean different client see each others data across method invocations? True, for both of these questions, if the same instance of the bean is taken from the pool for the two different requests.

Question:

I'm beginning to lean EJB, and I'm trying to run the sample: http://openejb.apache.org/examples-trunk/simple-stateless-with-descriptor/README.html

...and I got:

javax.naming.NoInitialContextException: Cannot instantiate class: simpleStatelessWithDescriptor.LocalInitialContextFactory [Root exception is java.lang.ClassNotFoundException: simpleStatelessWithDescriptor.LocalInitialContextFactory]
    at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:657)
    at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
    at javax.naming.InitialContext.init(InitialContext.java:223)
    at javax.naming.InitialContext.<init>(InitialContext.java:197)
    at simpleStatelessWithDescriptor.CalculatorTest.setUp(CalculatorTest.java:17)
    at junit.framework.TestCase.runBare(TestCase.java:139)
    at junit.framework.TestResult$1.protect(TestResult.java:122)
    at junit.framework.TestResult.runProtected(TestResult.java:142)
    at junit.framework.TestResult.run(TestResult.java:125)
    at junit.framework.TestCase.run(TestCase.java:129)
    at junit.framework.TestSuite.runTest(TestSuite.java:252)
    at junit.framework.TestSuite.run(TestSuite.java:247)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.ClassNotFoundException: simpleStatelessWithDescriptor.LocalInitialContextFactory
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:249)
    at com.sun.naming.internal.VersionHelper12.loadClass(VersionHelper12.java:46)
    at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:654)
    ... 18 more

My file tree is:

I searched and replaced in all file the package names to meet the file tree.

Now, what's still missing? Why it can't find the LocalInitialContextFactory?

I'm on Windows 10 64bits, Eclipse Neon, java 6 (can't update for now).


Answer:

simpleStatelessWithDescriptor.LocalInitialContextFactory doesn't exist in your classes and you should not declare it.

You should use org.apache.openejb.core.LocalInitialContextFactory if you follow the example. You have not the class in your classpath because I imagine you have not added it. Adding each needed library may be long and complex. You should use the pom.xml as proposed in the example.

Some advices if I can : Install Maven, learn the basis to use it, checkout the project from scratch and build it with Maven: http://svn.apache.org/repos/asf/tomee/tomee/trunk/examples/simple-stateless-with-descriptor/

Question:

I have Stateless EJB WebService.

WS interface:

@Remote  
@WebService
public interface WSInterface{  
    @WebMethod  
    public String[] WSMethod(@WebParam(name="arg0") String arg0)
}

WS implementation:

@WebService
@Stateless
public class WSImpl extends GenericSessionBean implements WSInterface {
    @WebMethod
    public String[] WSMethod( String arg0)
    {
        return ...;
    }
}

And i need to get client IP in WSMethod. I tried to get it by this way (it works in "common" webservice):

@Resource  
private SessionContext ctx;  
public String[] getProperties() {  
    List propList = new ArrayList();    
    MessageContext mc = ctx.getMessageContext();  
    Iterator props = mc.getPropertyNames();  
    for (String prop = (String)props.next(); props.hasNext(); prop = (String)props.next())  
        { propList.add(prop); }  
    return propList.toArray(new String[propList.size()]);
}

But no success: there is no property with name REMOTE_ADDR in MessageContext.

Is there any way to get REMOTE_ADDR in @Stateless EJB?


Answer:

Can you try to obtain a WebServiceContext instead of SessionContext with @Resource? I've no appropriate env to check it up right now