Since I'm struggling on documentation about CDI, I hope this question could become a useful resource for the correct CDI annotations to use in Jersey/Glassfish.
Say we have an application BookStore:
package my.bookstore;
import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
#ApplicationPath("/bookstore")
public class BookStore extends ResourceConfig {
public BookStore() {
this.packages("my.bookstore.resource");
}
}
We want to make Book entities accessible via a RESTful service:
package my.bookstore.entity;
public class Book {
public String isbn;
public String title;
public String author;
public Book(String isbn, String title, String author) {
this.isbn = isbn;
this.title = title;
this.author = author;
}
}
So we need a DAO to access the datastore:
package my.bookstore.dao;
import my.bookstore.entity.Book;
import java.util.List;
public interface BookDAO {
public List<Book> getAllBooks();
}
And its implementation:
package my.bookstore.dao;
import my.bookstore.entity.Book;
import java.util.List;
import java.util.ArrayList;
public class DefaultBookDAO implements BookDAO {
public List<Book> getAllBooks() {
List<Book> bookList = new ArrayList<>();
list.add(new Book("1234", "Awesome Book", "Some Author"));
return bookList;
}
}
Then I want to inject the DefaultBookDAO into the RESTful service:
package my.bookstore.resource;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/books")
public class BookResource {
#Inject
BookDAO dao;
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<Book> getBooks() {
return this.dao.getAllBooks();
}
}
Now, when deploying the application I get:
Unsatisfied dependencies for type BookDAO with qualifiers #Default
since I need to make CDI aware of it; but how? I tried various combinations of #Named, #Default, #Model, #Singleton, #Stateless and many resources such as questions and blog articles have they own interpretation of them.
What are the correct, plain CDI annotation to use to make this injection work in Jersey/Glassfish?
To me, it seems that you did not put beans.xml file into your application. With Glassfish 4 (generally with Java EE 7) this file is not required, however, if you omit it, only beans annotated with scope annotations are considered. Therefore, as DefaultBookDAO is not marked by any annotation, it is not considered by CDI as a candidate for injection.
You have 2 options to fix it and make CDI mechanism consider DefaultBookDAO:
put #Dependent annotation on DefaultBookDAO class - this will not change its scope, as #Dependent is the default scope, but will make CDI to consider this class
create beans.xml file in either META-INF or WEB-INF (for web apps) with the value of bean-discovery-mode="all"
In my opinion, the first option is cleaner - you may easily separate code which can be injected and which cannot. But if you want to increase productivity by omitting unnecessary annotations, go with the second option. It is more complicated, but you have to do it only once per module.
Please see this oracle blog post about beans.xml in Java EE 7 and the default behavior if it is omitted.
Since it is a service you can annotate your DefaultBookDAO with #Stateless.
Then you need an additional class implementing the AbstractBinder class.
It should look like this for your case:
import org.glassfish.hk2.utilities.binding.AbstractBinder;
public class MyApplicationBinder extends AbstractBinder {
#Override
protected void configure() {
bind(DefaultBookDAO.class).to(BookDAO.class);
}
}
You have to register this class in the class where you extend ResourceConfig like this:
#ApplicationPath("/bookstore")
public class BookStore extends ResourceConfig {
public BookStore() {
register(new MyApplicationBinder());
this.packages("my.bookstore.resource");
}
}
Then the #Inject should work.
See also:
Jersey docs: Chapter 22. Custom Injection and Lifecycle Management
Dependency injection with Jersey 2.0
Related
I'm still learning spring dependency injection in depth.
My first class is a configuration class, where i declare to the container to load and manage the beans declared in the annotated methods.
package ioc.question_004;
import ioc.commun.Person;
import ioc.commun.Profession;
import org.springframework.context.annotation.*;
#Configuration
public class MyConfiguration {
#Bean
public Profession profession(){
return Profession.builder()
.name("professor")
.description("professor in the university")
.build();
}
#Bean
public Person person(){
return Person.builder()
.name("Bagna")
.age(52)
.profession(profession())
.build();
}
}
My second class is a daoRepository, it looks likes:
package ioc.question_008.dao;
import ioc.commun.Person;
import lombok.*;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
#Repository
#Builder
#Setter
#Getter
#EqualsAndHashCode
#ToString
public class MyDaoRepository implements dao {
List<Person> personList = new ArrayList<>();
#Override
public boolean save( Person person ){
return this.personList.add(person);
}
#Override
public boolean delete( Person person ){
return this.personList.remove(person);
}
}
My running code is as follows:
#Configuration
#Import(MyConfiguration.class)
#ComponentScan(basePackageClasses = {MyDaoRepository.class} )
public class DependencyInjection {
public static void main( String[] args ) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DependencyInjection.class);
dao myDaoRepository = (MyDaoRepository) context.getBean("myDaoRepository");
System.out.println(myDaoRepository);
}
}
Magically MyDaoRepository contains the #Bean person declared in the configuration class MyConfiguration:
MyDaoRepository(personList=[Person(name=Bagna, age=52, profession=Profession(name=professor,
description=professor in the university))])
I thnik that the container injected this object automatically even if i didn't ask for that. May be some #Autowired annotation is added by the compiler. I'm not sure.
Could you please explain to me how i can ask the spring container to not inject the beans even if they exists in the container(the bean person for example), unless i ask the to do the injection by myself with the #Autowired annotation.
The reason is the combination of spring's autowiring of collections and lombok's Builder
First, the #Builder adds an all args constructor MyDaoRepository(List<Person> list).
Second, spring automatically detects your factory methods #Bean public Person person().
Now, since the constructor expects a collection, spring accumulates all Person-beans it can find into a List and injects it into the constructor, setting the list accordingly.
I think (but it is currently untested but documented here), that adding #Autowired(required = false) to your List<Person> persons property is what you want in this case, as that marks it as optional and spring will not inject it. (EDIT: I was mistaken, you still need the no-args-constructor for this to work, but without any #Autowired annotation the list would not get injected that way anyway. The required=false simply prevents the exception when no proper Person bean is found.)
EDIT: As Mr. Roddy, the Roddy of the Frozen Peas, pointed out, it would also be possible to add a different constructor for spring to create your bean, e.g. by annotating your repository with #NoArgsConstructor
I'm developing an SDK, which will be used to create additional applications for batch processing. There is core-a-api module, which holds interface Client
public interface Client {
void send();
}
and core-a-impl which holds couple implementations for Client interface - HttpClient and TcpClient.
Also, there is one more core module core-b-impl, which uses a particular instance of Client interface.
public class SendingTasklet implements Tasklet {
#Autowired
private Client client
public void process() {
client.send();
}
}
What instance should be created (HttpClient or SftpClient) should be decided by the user, who creates an application using SDK. He also needs to have an ability to create its own implementation for Client and use it in SendingTasklet. A user from core dependencies can see only interfaces from -api modules. For dependency injection, I'm using Spring. All beans for particular modules are created in each module separately. The user created beans are created in user's configuration class
#Configuration
public class UsersApplicationConf {
#Bean
public Client client {
return new UsersClient();
}
}
The issue is, that somehow without exposing -impl module details for user application, he should be able to decide what Client implementation can be used from the core provided implementations or he should be able to pass one of its own.
The first thought was to use qualifiers when injecting into SendingTasklet, but then you need to create a separate instance variable for each implementation in SendingTasklet and this is not very good because if there would be more implementations for Client interface it would be required to change SendingTasklet as well. And also the problem, that user should somehow decide wich implementation to use persists.
What I did, I exposed core-a-impl for client's application. So in his configuration, he can decide what instance to create for Client interface.
#Configuration
public class UsersApplicationConf {
#Bean
public Client client {
return new HttpClient();
}
}
But this is not very smart as well and I'm thinking is there any other way how to solve this issue?
You can use strategy or factory pattern as mentioned here but personally I would go with JSR 330 that you can find an example here , below code block for spring example:
package spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static spring.Spring.Platform;
#Configuration
#ComponentScan
public class Spring {
public static void main(String[] args) {
new AnnotationConfigApplicationContext(Spring.class);
}
#Autowired
#Platform(Platform.OperatingSystems.ANDROID)
private MarketPlace android;
#Autowired
#Platform(Platform.OperatingSystems.IOS)
private MarketPlace ios;
#PostConstruct
public void qualifyTheTweets() {
System.out.println("ios:" + this.ios);
System.out.println("android:" + this.android);
}
// the type has to be public!
#Target({ElementType.FIELD,
ElementType.METHOD,
ElementType.TYPE,
ElementType.PARAMETER})
#Retention(RetentionPolicy.RUNTIME)
#Qualifier
public static #interface Platform {
OperatingSystems value();
public static enum OperatingSystems {
IOS,
ANDROID
}
}
}
interface MarketPlace {
}
#Component
#Platform(Platform.OperatingSystems.IOS)
class AppleMarketPlace implements MarketPlace {
#Override
public String toString() {
return "apple";
}
}
#Component
#Platform(Platform.OperatingSystems.ANDROID)
class GoogleMarketPlace implements MarketPlace {
#Override
public String toString() {
return "android";
}
}
Edit: I didnt test the code but I have used javax.inject.Qualifier
with CDI if this code doesnt work let me know I will update with
correct combination and imports
I'm using Guice for dependency injection and I'm a bit confused. There are two Named annotations in different packages:
com.google.inject.name.Named and javax.inject.Named (JSR 330?).
I'm eager to depend on javax.inject.*. Code sample:
import javax.inject.Inject;
import javax.inject.Named;
public class MyClass
{
#Inject
#Named("APrefix_CustomerTypeProvider")
private CustomerTypeProvider customerTypeProvider;
}
In my naming module I may have the following line:
bind(CustomerTypeProvider.class).annotatedWith(...).toProvider(CustomerTypeProviderProvider.class);
The question: I'm curious what should I put where the dots are? I would expect something like com.google.inject.name.Names.named("APrefix_CustomerTypeProvider") but this one returns com.google.inject.name.Named while I need the one in javax.inject.
CustomerTypeProviderProvider.class.getAnnotation(javax.inject.Named.class) also does not fit well because the CustomerTypeProviderProvider (ignore the stupid name, legacy issue) is not annotated.
As mentioned on the Guice wiki, both work the same. You shouldn't worry about that. It is even recommended to use javax.inject.* when available, just as you prefer too (bottom of the same page).
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.name.Names;
import javax.inject.Inject;
public class Main {
static class Holder {
#Inject #javax.inject.Named("foo")
String javaNamed;
#Inject #com.google.inject.name.Named("foo")
String guiceNamed;
}
public static void main(String[] args) {
Holder holder = Guice.createInjector(new AbstractModule(){
#Override
protected void configure() {
// Only one injection, using c.g.i.Names.named("").
bind(String.class).annotatedWith(Names.named("foo")).toInstance("foo");
}
}).getInstance(Holder.class);
System.out.printf("javax.inject: %s%n", holder.javaNamed);
System.out.printf("guice: %s%n", holder.guiceNamed);
}
}
Prints:
java.inject: foo
guice: foo
I have never used guice before, and I wanted to try it out on an example project with jersey based JAX-RS API backed by a service-bean. I followed this guide: http://randomizedsort.blogspot.de/2011/05/using-guice-ified-jersey-in-embedded.html and was able to bring it to work. My setup is very simple, a JAX-RS resource is invoked via Guice and has a field that is annotated #Inject and injected by Guice:
#Path("configuration")
#Produces(MediaType.APPLICATION_JSON)
#Singleton
public class ConfigurationResource {
#Inject
private ConfigurationService configurationService;
So far so good, everything works like it should, besides following: I am using GuiceServletContextListener for setting things up and have to name each component explicitly:
#WebListener
public class GuiceInitializer extends GuiceServletContextListener{
#Override
protected Injector getInjector() {
return Guice.createInjector(new JerseyServletModule() {
#Override
protected void configureServlets() {
//resources
bind(ConfigurationResource.class);
//services
bind(ConfigurationService.class).to(ConfigurationServiceImpl.class);
// Route all requests through GuiceContainer
serve("/management/*").with(GuiceContainer.class);
}
});
}
}
I find it pretty inconvenient to explicitly name all dependencies. I have worked with standalone jersey before and it's perfectly capable of auto-scanning for resources in defined packages. Also Spring and CDI are capable of mapping implementation to interfaces without need to explicitly name them.
Now the question part:
is there any autoscan extension/setting for guice? I found some on the internet, but it's hard to tell which of them are still useable and uptodate.
is there any other possibility to make configuration of implementations and resources more convenient?
thanks in advance.
Leon
I do not think Guice has built in support for someting like the component-scan of Spring framework. However, it is not difficult to simulate this feature in Guice.
You simply need to write a helper module like the following
import com.google.inject.AbstractModule;
import org.reflections.Reflections;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* To use this helper module, call install(new ComponentScanModule("com.foo", Named.class); in the configure method of
* another module class.
*/
public final class ComponentScanModule extends AbstractModule {
private final String packageName;
private final Set<Class<? extends Annotation>> bindingAnnotations;
#SafeVarargs
public ComponentScanModule(String packageName, final Class<? extends Annotation>... bindingAnnotations) {
this.packageName = packageName;
this.bindingAnnotations = new HashSet<>(Arrays.asList(bindingAnnotations));
}
#Override
public void configure() {
Reflections packageReflections = new Reflections(packageName);
bindingAnnotations.stream()
.map(packageReflections::getTypesAnnotatedWith)
.flatMap(Set::stream)
.forEach(this::bind);
}
}
To component scan a package like com.foo and sub packages for classes carrying #Singleton, use it in this way:
public class AppModule extends AbstractModule {
public void configure() {
install(new ComponentScanModule("com.foo", Singleton.class));
}
}
I consider injection of beans as a List of automatically detected beans: I introduce several beans implementing the same interface and inject all of them as a List in a later bean.
I've not been able to find official documentation related to this feature. My single source is http://www.coderanch.com/t/605509/Spring/Java-config-autowired-List
Considering this feature, I have an issue with Bean overring: I would like to override a bean defined throught a no-arg method with a bean defined with the List of detected beans. However, spring behave like the second bean definition does not exist.
It can be reproduced with the following test:
import java.util.Date;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public class SpringTest {
#Test
public void shouldtestSpringDifferentMethodNames() {
AnnotationConfigApplicationContext ctx2 = new AnnotationConfigApplicationContext(AConfig.class, CConfig.class);
Assert.assertEquals("overriden", ctx2.getBean("bean"));
}
#Configuration
public static class AConfig {
#Bean
public Object bean() {
return "not overriden";
}
}
#Configuration
public static class CConfig extends AConfig {
#Bean
public Date anotherBean() {
return new Date();
}
#Bean
public Object bean(List<? extends Date> someDate) {
return "overriden";
}
}
}
If this is an expected behavior, how can I achieve such an overriding?
documentation for list autowire can be found at spring documentation
overriding of beans by id or name is not official spring feature - look for that question for more details
This has been considered as a bug by the Spring team: https://jira.springsource.org/browse/SPR-10988
A recent piece of documentation can be found at: http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-autowired-annotation (Thanks Alexander Kudrevatykh for the 2.5 source)