Search code examples
jakarta-eedependency-injectionejbjax-rs

Interface-EJB not injected in no-interface-EJB


Awaiting answers.

I've a JAX-RS controller (Jersey 2.21 on WildFly 9.0).

@Named
@Path("v1/populateList/")
public class PopulateDataController {

    @EJB
    ListItemService listItemService;

    @GET
    @Path("auto")
    @Produces(MediaType.TEXT_PLAIN)
    public String populateList(){
        listItemService.populateList();
        return "done";
    }
}

The below ListItemService no-interface EJB is successfully injected in above JAX-RS controller.

@Stateless
public class ListItemService {

    @EJB
    ListItemDao listItemDao;

    public void populateList(){
        listItemDao.persist();
    }
}

However, the below ListItemDaoImpl interface-EJB is not in turn injected in above no-interface EJB.

@Stateless
public class ListItemDaoImpl implements ListItemDao{

    @PersistenceContext(unitName = "pu")
    private EntityManager em;

    public void persist(){
        ListItem listItem = new ListItem();
        listItem.setLevel(1);
        listItem.setName("item1");
        em.persist(listItem);
    }
}

The listItemDao remains null in populateList() method of ListItemService, causing NullPointerException.

How is this caused and how can I solve it?

--- Edit and update ---

I tried to make a Singleton bean to run on startup (to check my app logic). It works fine without JAX RS. So its clear that the problem is not with EJB but JAX RS. (Do correct me if wrong)

    @Singleton
    @Startup
    public class TestController {
        @EJB
        ListItemService listItemService;

        @PostConstruct
        void test(){
        System.out.println("starting..........");
        listItemService.populateList();
        System.out.println("ending..........");
        }

    }

Solution

  • Creating the following class helped.

        @javax.ws.rs.ApplicationPath("api")
        public class InjectionApplication extends javax.ws.rs.core.Application {
            private Set<Object> singletons = new HashSet<Object>();
            private Set<Class<?>> classes = new HashSet<Class<?>>();
    
            public InjectionApplication() {
            // no instance is created, just class is listed
            classes.add(ListItemController.class); //replace with yours
            classes.add(ParseFeedController.class); //replace with yours
            //add more or use some auto class finding technique
    
            }
    
            @Override
            public Set<Class<?>> getClasses() {
            return classes;
            }
    
            @Override
            public Set<Object> getSingletons() {
            return singletons;
            }
        }