How do I inject an EJB in Spring MVC using annotations? - spring-mvc

My dispatcher-servlet.xml has basically:
<context:component-scan base package="package.ejb" />
<mvc:annotation-driven />
In the #Controller class I have:
#Controller
public class ApplicationController {
#EJB(lookup="java:global/MyEarName/MyWebModuleName/BeanImplementation!package.ejb.morepackages.BeanImplementation")
private MyBeanInterface myBean;
This didn't work, it looks like Spring doesn't see the #EJB annotation and it gives an error at deploy time saying it doesn't find any Autowire candidate. So I added the following code:
#Autowired
#Qualifier("BeanImplementation")
public void setMyBean(MyBeanInterface myBean) {
this.myBean = myBean;
}
And on my bean implementation:
#Component("BeanImplementation")
#Stateless(mappedName = "BeanImplementation", name = "BeanImplementation")
#LocalBean
public class BeanImplementation implements MyBeanInterface {
It worked, but I need to use the lookup string of the EJB and I can't since Spring doesn't see #EJB. I was forced to revert to a non-Spring application to use #EJB(lookup="...").
So, to clarify the question: how do I inject an EJB in Spring MVC using annotations and using the EJB lookup string? Thanks.

Related

Please help to explain a strange combination of Lombok's #AllArgsConstructor and spring's #RestController

I'm working on a spring project from our customer.
Below is the code for controller
#Log4j2
#RestController
#AllArgsConstructor
#RequestMapping(path = "/api/theapi")
#Api(value = "Description for the API")
public class TheAPIController {
private final ModelMapper modelMapper;
private final ObjectMapper objectMapper;
private final TheDemoService demoService;
...other code for controller
}
Below is the code for Service:
#Service
public class TheDemoService{ ... }
I was so surprise about 2 things:
Question 1: Why we need to use #AllArgsConstructor from project Lombok?
As per my understanding, Spring provide #RestController that Spring runtime container will initialize an Instance for our Controller. So that, having a constructor for our Controller seems like an invalid approach for using Spring Inversion of Control, is this correct?
Question 2. Because of using #AllArgsConstructor, somehow, the instance for demoService is to be injected
But again, I surprise because the code of Controller does not have #Autowired in combine with demoService.
In the actual code, there is no #Autowired for "private final TheDemoService demoService".
Hence, I could think of a possibility there, is that because of Lombok's #AllArgsConstructor would inject an instance of our TheDemoService via a constructor of
TheAPIController, I could not reason anything about this logic.
It's Invalid approach, no need for defining constructor for RestController
It's implicitly auto wiring the service
if a class, which is configured as a Spring bean, has only one constructor, the Autowired annotation can be omitted and Spring will use that constructor and inject all necessary dependencies.
To sum up #AllArgsConstructor can/should be removed

Spring #EventListener annotation doesn't work with #Service annotation

Here are two objects I want to receive ContextRefreshedEvent
#Component
public class InitDB {
#EventListener
public void handleContextRefresh(ContextRefreshedEvent e) {
//
}
}
InitDB works as expected, but in this case not:
#Service
public class MyService implements IMyService{
#Autowired
private MyDao _dao; // Autowired WORKs
#EventListener
public void handleContextRefresh(ContextRefreshedEvent e) {
// DOESN'T WORK
}
[...]
}
Any Idea what I'm doing wrong?
Here are my maven properties
<properties>
<java-version>1.7</java-version>
<org.springframework-version>4.2.2.RELEASE</org.springframework-version>
<spring-security-web-version>3.2.5.RELEASE</spring-security-web-version>
<org.aspectj-version>1.7.2</org.aspectj-version>
<org.slf4j-version>1.5.10</org.slf4j-version>
<hibernate-version>4.3.6.Final</hibernate-version>
<json-jackson-version>2.4.1</json-jackson-version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<skipTests>true</skipTests>
</properties>
I had the same problem and for me, it proved my listener bean wasn't loaded in the dependencies by Spring.
If you use Spring Boot Actuator, you can check the loaded beans at https://localhost:8443/beans.
The bean wasn't detected by Spring because I had a namespace typo. My main namespace was com.foo (with packages like com.foo.security and com.foo.controllers), and when I added a new package logging, I introduced a typo in the namespace: com.ffoo.logging.
Because of this, Spring could not find the new Components/Services I was adding.
For this particular question, it doesn't matter if it's annotated with #Service, because #Service is a sub-class of #Component (see post)

How should look configuration for multiple controllers in Spring MVC?

I have 2 logical items News and Cars. For each of them I need to have separate controllers. How I should configure my application.
If youre using annotation based configuration, you can simply create 2 Classes that are annotated with #Controller, like:
package com.example.controllers;
#Controller
public class NewsController {
#RequestMapping(value = "/news")
public String handleNewsCall() {
...
}
}
and
package com.example.controllers;
#Controller
public class CarsController {
#RequestMapping(value = "/cars")
public String handleCarsCall() {
...
}
}
Don't forget to add the following lines to your spring xml if you use annotation based configuration.
<context:component-scan base-package="com.example" />
<mvc:annotation-driven />

Best way to pass reference of injected dependency in spring controller

I have a Spring portlet controller class. In this class, there is a dependency like this:
#Autowired
protected ServiceClass someService;
#Autowired
protected ApplicationContext context;
From the controller, there is a utility class being called like this:
UtilityClass.loadStaticData((WebApplicationContext)context);
Inside UtilityClass, I have:
public static synchronized boolean loadStaticData(WebApplicationContext context){
ServiceClass someService = (ServiceClass) context.getBean("someService");
...
}
My question is: Is there any advantage to getting the handle of the someService in such a complicated way? We could have just passed the reference 'someService' from Controller class #1 to the UtilityClass. The author is no longer available so I am asking here.
This is basically what dependency injection tries to avoid: getting a dependency from the container instead of having the dependency injected by the container.
This utility class should be a Spring bean, where the service would be injected. And you could then inject this utility bean inside the controller.

WELD-001408 Unsatisfied dependencies when injecting EJBs that implement interfaces

Here is the situation.
I've got the following interfaces:
public interface Parent { }
public interface ChildOne extends Parent { }
public interface ChildTwo extends Parent { }
and 2 EJBs:
#Stateless
public class FirstBean implements ChildOne { }
#Stateless
public class SecondBean implements ChildTwo { }
And also this CDI Bean:
#Named
#SessionScoped
public class TestController implements Serializable {
#Inject
private FirstBean firstBean;
#Inject
private SecondBean secondBean;
}
While trying to deploy this on Glassfish 3.1 I get the following exception:
Exception while loading the app : WELD-001408 Unsatisfied dependencies for type [FirstBean]
with qualifiers [#Default] at injection point [[field] #Inject private com.test.controllers.TestController.firstBean]
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [FirstBean]
with qualifiers [#Default] at injection point [[field] #Inject private com.test.controllers.TestController.firstBean]
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:305)
When both EJBs implement the Parent interface, the exception is the same.
Also, I tried adding qualifiers, but that didn't change anything.
I just played around with your construct, read a bit of the weld docu and found out the following.
You are using EJBs that implement an interface, so the no-interface view is not possible anymore (obviously), but you are trying to directly access the implementation. As soon as you declare it as an EJB you have to keep in mind the conventions. So, if you define an interface you have to use it to get access to the EJB. Changing it to the following, should work out:
#Inject
private ChildOne firstBean;
Accessing the implementation even though an interface is defined is just possible for plain CDI Managed Beans (classes without the #Stateless/#Stateful annotations). So get rid of your annotation and it will work out.
Just for your information, if you are using Glassfish. If you stick to your EJBs and try to access the parent interfaces method you will run into this bug / exception.
Better late than never:
Annotating the SLSB aditionally with #LocalBean works for me with JBoss AS 7.1.1. I don't like the idea of creating the interface for no added value.
Using your example:
#Stateless
#LocalBean
public class FirstBean implements ChildOne { }
#Stateless
#LocalBean
public class SecondBean implements ChildTwo { }
Have you tried using #EJB annotation rather then the CDI #inject annotation?
E.g.
#Named
#SessionScoped
public class TestController implements Serializable {
#EJB
private FirstBean firstBean;
#EJB
private SecondBean secondBean;
}

Resources