Jersey constructor with parameters - java

I want to use a DAO in my RESTful service developed with Jersey, so the DAO implementation should be injected via the constructor of the service:
#Path("eventscheduler)
public class EventSchedulerService {
private IEventSchedulerDao dao;
public EventSchedulerService(IEventSchedulerDao dao) { this.dao = dao; }
}
However, I know Jersey expects a default constructor to setup everything correctly. I have been trying to figure out how to do this for a while but surprisingly this seems to be an uncommon case, I wonder how people inject DAOs into their services, or deal with injection in general at all.
How can I do this?

If you're using Jersey 2, it uses HK2 as it's DI framework. All resource classes go through the DI lifecycle when they are constructed. And constructor injection is not a problem.
The most basic way (with Jersey) to make an arbitrary object injectable, is to bind in an AbstractBinder
public class Binder extends AbstractBinder {
#Override
protected void configure() {
bind(EventSchedudlerDaoImpl.class).to(EventSchedulerDao.class);
}
}
Then register the binder with Jersey
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(new Binder());
}
}
Then you just need to declare the injection point by adding #Inject on top of the constructor.
#Inject
public EventSchedulerService(EventSchedulerDao dao) {
this.dao = dao;
}
As far as the binder implementation, the binding syntax basically reads as
bind( Implementation ).to( Contract ).in( Scope );
The bind method can take an instance or it can take a class. When you provide an instance, the Scope is automatically Singleton.
The to method specifies the advertised contract, which is the type that can be declared at the injection point. In this case, only the interface EventSchedulerDao can be used for the injection point. If you don't have an interface you can just do
bindAsContract(EventSchedulerDao.class)
assuming EventSchedulerDao is the implementation class.
The scopes available are PerLookup, RequestScoped and Singleton. If not specified, the default scope will be PerLookup, meaning a new instance of the service will be created for each injection point. You should already know what Singleton means. RequestScoped means that a new instance will be created for each request, which may not be the same as PerLookup, as the service may be injected at multiple points through out the request lifeclyle.
See Also:
Dependency injection with Jersey 2.0
Custom Injection and Lifecycle Management
hk2 tagged questions. Alot of them are Jersey related.

You must annotate the class constructor (or the property itself) with javax.inject.Inject.
import javax.inject.Inject;
class EventSchedulerResource {
private final IEventSchedulerDao dao;
#Inject
public EventSchedulerResource(IEventSchedulerDao dao) {
this.dao = dao;
}
// ...
}
If the IEventScheduler is an interface you must create a configuration class class that extends org.glassfish.jersey.server.ResourceConfig and register the binding of interface to a concrete implementation with bind(EventSchedulerDaoImpl.class).to(IEventScheduler.class) (See here: https://jersey.java.net/documentation/latest/ioc.html chapter 23.1)

Related

Spring Boot: Why does #Autowired not work for this case?

I have a Spring Boot Java application and am trying to inject a #Service into a class. I'm using #Autowired but it's not doing it. I successfully do so in other classes, but not this one.
The service class:
#Service
#Transactional
public class TaskService {
...
}
The class where it works is a Vaadin "view" annotated with a Vaadin #Route annotation. I'm assuming there is something going on behind the scenes with the #Route annotation that allows this to work.
#Route("main")
public class TaskListView extends HorizontalLayout {
private final TaskService taskService;
public TaskListView(#Autowired TaskService taskService) {
this.taskService = taskService;
}
...
}
The class where it does not work is also a Vaadin "view", but does not have a #Route annotation, because it is not intended to be navigable to, but rather used as a sub-component of a view (i.e. would be directly instantiated inside a parent view).
public class EditNotesForm extends VerticalLayout {
#Autowired
private TaskService taskService;
...
}
The first class uses constructor injection, while the second uses property injection. I can't see why this should make a difference, as I have used both techniques successfully in other applications.
From the Vaadin website:
The only difference between using the router in a standard application and a Spring application is that, in Spring, you can use dependency injection in components annotated with #Route. These components are instantiated by Spring and become Spring-initialized beans. In particular, this means you can autowire other Spring-managed beans.
One way to access Spring components from your regular Vaadin components is by creating static get methods to retrieve your Spring components. Here is one way that can be done... but not the only.
#Component
public class StaticHelper {
private static StaticHelper instance;
#Autowired
private ApplicationContext applicationContext;
#PostConstruct
public void registerInstance() {
instance = this;
}
public static <T> T getBean(Class<T> class) {
return instance.applicationContext.getBean(class);
}
}
So in your example...
private TaskService taskService = StaticHelper.getBean(TaskService.class);
Since EditNotesFormdoesn't have the Route annotation, spring can't autodiscover it and therefore it can't inject any dependency.
Since you want to instantiate it manually, you'll need to provide yourself all dependencies.
But if you still want to benefit from automatic dependency injection, take a look at https://www.baeldung.com/spring-beanfactory

CDI best way for passing services

I have several service like that:
#Singleton
public SimpleService {
...
}
I have Managed Bean #ViewScoped which should create some complex objects. These objects should execute business-logic. I need to pass these services to this object.
Example of Managed Bean:
#ManagedBean
#ViewScoped
public class ExampleBean {
#Inject
private SimpleService simpleService;
...
public void customLogic() {
// in this method I should create complex object which should have services and some data.
// current implementation
ComplexObject object = new ComplexObject(SimpleService simpleService, ...)
}
}
Services are injected to Managed Bean by #Inject annotation. For creating these objects - I'm using the constructor and pass these services as params. The question is: can I have better solution than passing services in constructor?
You can:
Inject by method:
private MyService myService;
#Inject
public void setMyService(MyService ms) {
this.myService = ms;
}
Inject by field:
#Inject
private MyService myService;
Fetch reference through CDI (not recommended, except in advanced usecases):
...
MyService myService = CDI.current().select(MyService.class).get();
...
Fetch reference through BeanManager (not recommended, except in advanced usecases or CDI 1.0):
...
BeanManager beanManager = CDI.getBeanManager(); // you can fetch a BeanManager reference by several other methods, I use CDI for simplicity here
MyService myService = beanManager.getReference(MyService.class);
...
If your #Singleton annotation is javax.ejb.Singleton and not javax.inject.Singleton, then your bean is actually a EJB and you can also use any mechanism that allows you to access EJB, such as #Resource annotations, or through the JNDI context.
Personally I tend to inject by method as I find it the most flexible option most of the time. In my opinion it is also the most "portable" to other frameworks (e.g: Spring)
Remember that when you use either the CDI.current() or the BeanManager methods to fetch #Dependent beans, you are responsible to manually destroy the fetched bean when you are done with it, so that you do not fall into this CDI-related memory leak. When using CDI.current() it is as easy as saving the Instance reference and invoking it afterwards:
...
Instance<MyService> msInstance = CDI.current().select(MyService.class);
MyService myService = msInstance.get();
...
msInstance.destroy(myService);
...
The BeanManager method is too low-level and should only be used in CDI 1.0 environments (back when the CDI class did not exist yet). You can read the linked StackOverflow question for more details.
What you are doing is perfectly fine. You are using the ManagedBean as a bridge to inject the services and then passing the injected variables to a ComplexObject that need the services.
The only restriction that should be considered is, could the ComplexObject class be a ManagedBean itself? That way you could inject everything directly on it, but if it is not possible, you may use the bean for that.
I prefer the inject by field option mentioned because I think it is a little more readable.

#Inject and #PostConstruct not working in singleton pattern

I have a class as below:
public class UserAuthenticator {
private static UserAuthenticator authenticator =
#Inject
private UserRepository userRepository;
#PostConstruct
public void init() {
List<User> allUsers = userRepository.findAll();
for (User user : allUsers) {
users.put(user.getEmail(), user.getPassword());
serviceKeys.put(user.getServiceKey(), user.getEmail());
}
}
public static UserAuthenticator getInstance() {
if (authenticator == null) {
authenticator = new UserAuthenticator();
}
return authenticator;
}
}
When I call
UserAuthenticator authenticator = UserAuthenticator.getInstance();
init() method isn't called and userRepository is null
My web application run in JBOSS EAP 6.3.
How is this caused and how can I solve it?
In a Java EE application, don't think in singletons. That's only recipe for trouble and confusion. Instead, think in "just create one". Tell the Java EE container to just create only one instance of the specified class, application wide, and obtain the instance via the facility offered by the Java EE container. Your concrete problem is caused because you're manually creating an instance of the class using new operator without manually performing the injection and post construct call like as the technical correct but conceptually wrong example below:
authenticator = new UserAuthenticator();
authenticator.userRepository = new UserRepository();
authenticator.init();
In other words, you incorrectly expected that the new operator magically recognizes the bean management and dependency injection related annotations.
The right approach depends on the one you'd like to point out as the responsible for creating and managing the instance of the specified class. If it's CDI, then just tell it to create only one managed bean instance of the backing bean class, application wide, using #Named #ApplicationScoped.
import javax.inject.Named;
import javax.enterprise.context.ApplicationScoped;
#Named
#ApplicationScoped
public class UserAuthenticator {}
It will be created just once and be available via #Inject as below in any other Java EE managed artifact (read: in any other class annotated with #Named, #Stateless, #ManagedBean, #WebServlet, #WebListener, #WebFilter, #Path, etc..):
#Inject
private UserAuthenticator userAuthenticator;
If you're absolutely positive that you need a static method to grab the current CDI managed bean instance of a given backing class, then you should be obtaining it via BeanManager as below instead of manually constructing the instance (assuming Java EE 7 / CDI 1.1 available):
#SuppressWarnings("unchecked")
public static <T> T getCurrentInstance(Class<T> beanClass) {
BeanManager beanManager = CDI.current().getBeanManager();
Bean<T> bean = (Bean<T>) beanManager.resolve(beanManager.getBeans(beanClass));
return (T) beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));
}
Usage:
UserAuthenticator userAuthenticator = YourCDIUtil.getCurrentInstance(UserAuthenticator.class);
// ...
See also:
Java singleton class vs JSF application scoped managed bean - differences?
Java EE 6 and Singletons
Well i think you shouldn't explictly call UserAuthenticator.getInstance() but to define the UserAuthenticator for example as #ApplicationScoped and get the instance via DI provided by your app server (#Inject).
UserAuthenticator should be then initialized properly.
The #PostConstruct method will not be invoked until you do some action on that class (ex: call some methods

Proper way of injecting dependencies?

Which one is the best way of injecting my dependencies? Why?
What is the difference between the two?
public abstract class Service {
private IConfig config;
#Inject
public Service(IConfog config) {
this.config = config
}
}
Or
public abstract class Service {
#Inject private IConfig config;
#Inject
public Service() {
}
}
Constructor injection (1st) is preferred over setter injection given that it makes it easier to support "immutable" entities or entities whose behaviour is well defined and non-modifiable after construction. Constructor vs Setter inject
For me the rule of thumb is to first prefer constructor injection and jump off to setter injection if constructor inject requires me to bend my back i.e. when working with legacy code with "OOP getter and setter" methods.
EDIT: I'm assuming you are trying to decide between "constructor" and "setter" constructor. But it also seems that you are using abstract classes which can't be instantiated. Maybe you have something else in mind?
First of all, I do not put injection-related annotations in abstract classes - in my opinion there is no sense in deciding how something should be instantiated if it actually cannot be instantiated (of course that's only my opinion with which others may agree or not).
Usually I do it in the following way:
public abstract class AbstractService {
private IConfig config;
public AbstractService(IConfog config) {
this.config = config
}
}
public class Service extends AbstractService {
#Inject
public Service(IConfig config) {
super(config);
}
}
Now, you can use both classes with and without dependency injection (construct it by hand, passing all required references). Also you can be sure that Service is instantiated in the appropriate state every time.
The main goal of dependency injection is to make unit testing easy by allowing to do
Service serviceToTest = new Service(mockConfig);
or
Service serviceToTest = new Service();
serviceToTest.setConfig(mockConfig);
The second way of injecting dependencies makes it impossible to do the abover. You can only test it by letting Guice create the service and inject a mock dependency, or by using reflection to set the mock dependency.

Injecting dependencies using #Autowired into objects created with "new ..."

I have a problem with injecting a bean into a helper class. It works basically like this: I create an object in the page constructor that does some work, returns some data and I show these on the page. In this helper object, a service should be injected via #Autowired annotation. However, I always get a null pointer exception when I use it. I also tried #SpringBean but it didn't help. On the other hand, when I inject this service directly into the page with #SpringBean, it's accessible and works fine. Do you know where the problem is?
This is the page:
public class Page extends BasePage {
public Page() {
HelperObject object = new HelperObject(new Application("APP_NAME"));
String result = object.getData();
add(new Label("label", result));
}
}
Helper object:
public class HelperObject {
private Application app;
#Autowired
private Service service;
public HelperObject(Application app) {
this.app = app;
}
public String getData() {
// use service, manipulate data, return a string
}
}
You can inject dependencies into non-Spring-non-Wicket-new-created objects using #SpringBean by calling InjectorHolder.getInjector().inject(this); in its constructor.
For example:
class MyPojo {
#SpringBean
MyDumbDAO dao;
MyPojo() {
InjectorHolder.getInjector().inject(this);
}
void justDoIt() {
dao.duh(); // dao is there!
}
}
Note that it will only work if called within a Wicket-managed request. If not (ie, if it's a Quartz job, or a Filter executed before Wicket's), the Application instance will not be available, and the injector won't know how to get the dependencies.
Another solution is to use Spring's #Configurable. It uses AspectJ to intercept creation of annotated objects, and inject its dependencies, even if you instantiate them directly with new (or some other framework, like Hibernate, creates them internally). But this requires runtime or build-time (works better for me) bytecode manipulation, which may be too much magic for some people.
#SpringBean only injects dependencies into classes that inherit from Wicket's Component. #Autowired only injects dependencies into classes created by Spring itself. That means you can't automatically inject a dependency into an object you create with new.
(Edit: you can also add a #SpringBean injection to your class by injecting in the constructor:
InjectorHolder.getInjector().inject(this);)
My normal workaround for this is to use my application class to help. (I'm a little puzzled by your use of new Application(...). I assume this isn't actually org.apache.wicket.Application.) For example:
public class MyApplication extends AuthenticatedWebApplication implements
ApplicationContextAware {
private ApplicationContext ctx;
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.ctx = applicationContext;
}
public static MyApplication get() {
return (MyApplication) WebApplication.get();
}
public static Object getSpringBean(String bean) {
return get().ctx.getBean(bean);
}
public static <T> T getSpringBean(Class<T> bean) {
return get().ctx.getBean(bean);
}
....
}
In my Spring application context:
<!-- Set up wicket application -->
<bean id="wicketApplication" class="uk.co.humboldt.Project.MyApplication"/>
My helper object then looks up the service on demand:
public class HelperObject {
private Service getService() {
return MyApplication.getSpringBean(Service.class);
}
The best practice would be to create your objects via a factory bean (that has those properties injected by Spring, and have that factory inject those properties to objects it spawns - pure IoC).
You should really avoid using SpringContext all over the place (or any other similar solution for that matter).
Here is a partial list of reasons:
Your code gets coupled with Spring way too much (low-cohesion).
You mix plumbing code with the business-logic.
Your code is less readable.
It's less maintainable (e.g., changing the name of the service bean would lead to code modification - this violates SRP & OCP).
It's less testable (e.g., you need the Spring framework to test it).

Categories

Resources