Can I use specific method for dependency injection in ejb? - java

For example I have a class that gets a dependecy in constructor, like
class ExampleService() {
private Dependency dep;
public ExampleService(Dependency dep) {
this.dep = dep;
}
}
and Dependecy class:
class Dependency {
public static Dependency getInstance() {
return new Dependency();
}
private Dependency() {
/*constructor implementation here*/
}
}
I want to inject result of Dependency.getInstance() method into ExampleService constructor by #Inject EJB annotation. Is it possible? How? Thankyou.

In CDI a producer method can be static, so using your example, the following would work just fine:
class ExampleService() {
private Dependency dep;
#Inject
public ExampleService(Dependency dep) {
this.dep = dep;
}
}
class Dependency {
#Produces
public static Dependency getInstance() {
return new Dependency();
}
private Dependency() {
/*constructor implementation here*/
}
}
However, like mentioned in the comments to your question, there might be better ways depending on what you want.

Related

How to inject bean via generic variable in spring

I have problem with injecting bean with generic types. Look at the example. I will inject to the service a repository which types takes from App class. Now i have exception:
No qualifying bean of type 'asd.IRepository' available: expected single matching bean but found 2: a,b
asd here is package, just for tests.
What can I do in this situation? Is any way to makes it?
public interface IRepository<T, V> {
void print();
}
#Component
public class A implements IRepository<String,String> {
#Override
public void print() {
System.out.println("A");
}
}
#Component
public class B implements IRepository<Double,String> {
#Override
public void print() {
System.out.println("A");
}
}
#Service
public class ServiceABC<V, T> {
#Autowired
private IRepository<V,T> repo;
public void print(){
repo.print();
}
}
#Controller
public class App {
#Autowired
private ServiceABC<String, String> serviceABC;
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext("asd");
App app = ctx.getBean(App.class);
app.serviceABC.print();
}
It looks like you don't know in advance which implementation of your IRepository interface you will need. And you will know that at runtime. In this case it is a typical case for Factory pattern where you will have a IRepositoryFactory that will have a method thhat retrieves specific implementation by type (for example IRepositoryFactory.getInstance(String type); So in your ServiceABC you may use the IRepository to get specific bean at runtime. So Factory pattern may be an answer to your question. I also wrote an article that deals with this type of problem and proposes the idea of self-populating Factory (using Open source library that provides such utility). Here is the link to the article: Non-intrusive access to "Orphaned" Beans in Spring framework
You have to name your components and autowire by name:
#Component("A")
public class A implements IRepository<String,String> {...}
#Component("B")
public class B implements IRepository<Double,String> {...}
[...]
#Autowired
#Qualifier("B")
private IRepository repo;
Something like that?
#Controller
public class RepositoryFactory {
#Autowired
private IRepository<String, String> a;
#Autowired
private IRepository<Double, String> b;
public IRepository getRepository(String className) {
if(className.equalsIgnoreCase("a")) {
return a;
} else if(className.equalsIgnoreCase("b")) {
return b;
}
return null;
}
}
#Service
public class ServiceABC {
#Autowired
private RepositoryFactory repositoryFactory;
public void print(String className){
repositoryFactory.getRepository(className).print();
}
}
#Controller
public class App {
#Autowired
private ServiceABC serviceABC;
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext("asd");
App app = ctx.getBean(App.class);
app.serviceABC.print(A.class.getSimpleName());
}
}s

Spring 4 Component Inject with generic

I have encountered with the following issue. I would like to create Spring #Component with generic
#Component
public class ResponseDtoValidator<DTO> {
public ResponseEntity<DTO> methodToInvoke(DTO dto) {
return Optional.ofNullable(dto).map(result -> new >ResponseEntity<>
(result, HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND)); }
}
#Controller
public class SomeController {
#Inject
private ResponseDtoValidator<DTO1> responseDtoValidator1;
#Inject
private ResponseDtoValidator<DTO2> responseDtoValidator2;
public void someMethod() {
DTO1 dto1 = new DTO1();
DTO2 dto2 = new DTO2();
responseDtoValidator1.methodToInvoke(dto1);
responseDtoValidator2.methodToInvoke(dto2);
}
}
Can I inject this Component like above? Actually, I have tried and it seems to work properly, can you please confirm that I am correct or not?
Firstly, a spring bean can not be injected in itself.
In regards to your question,yes it is injectable but dont use generic signs when injecting. Just inject it normally. Generic type is send when a method of generic class is utilizing.
For instance;
#Component
public class ResponseDtoValidator<DTO> {
public void getAbc(List<DTO> aList) {}
}
Then;
public class Test {
#Autowired // or #Inject
private ResponseDtoValidator responseDtoValidator;
public void testMethod() {
responseDtoValidator.getAbc(List<EnterATypeInHere> aList);
}
}

Dagger 2 inject singleton without module

I am using Dagger 2 injection to provide some dependency to client:
public class Dependency {
#Inject
Dependency() {
}
void check() {
System.out.print("Instantiated");
}
}
public class Client {
#Inject Dependency dependency;
Client() {
ClientComponent component = DaggerClientComponent.create();
component.inject(this);
}
void checkDependency() {
dependency.check();
}
}
#Component
public interface ClientComponent {
void inject(Client client);
}
public class Test {
public static void main(String... args) {
Client client = new Client();
client.checkDependency();
}
}
It works fine, but now I want to make my dependency singleton. How can I achieve it? Should I create module for this dependency and annotate provide method with singleton annotation or I have another options to avoid module creation?
Add #Singleton on the top of your class and add #Singleton annotation to your component.
#Singleton
public class Dependency {
#Inject
Dependency() {
}
void check() {
System.out.print("Instantiated");
}
}
#Singleton
#Component
public interface ClientComponent {
void inject(Client client);
}
You should also move creation of your component to better place - onCreate method from app object is right place.

Does method injection with Guice work if constructor is not injected?

I have a class where I need to inject a variable but the constructor is not guice injected.
public class Foo{
private boolean x;
public Foo(){
//sets some variables
}
#Inject
public void setX(boolean x){
this.x=x;
}
}
The value of x is not getting injected. Is it necessary to use injection in constructor for guice to recognize method injection?
Do I need to call this method from some other class for this to work?
Thanx in advance
If you're going to use Guice to #Inject Foo then Guice needs to create the object - either from the injector or from another #Inject point in separate class. Guice can't help you inject objects that it didn't create.
In this case it's not necessary to add #Inject to the constructor because Guice can automatically inject a no argument constructor. For example:
public class MethodInjectionTest {
static class Foo {
private boolean x;
public Foo(){
//sets some variables
}
#Inject
public void setX(boolean x){
this.x=x;
}
}
Injector i = Guice.createInjector(new AbstractModule() {
protected void configure() {
bind(Boolean.class).toInstance(Boolean.TRUE);
}
});
#Test
public void methodInjection() {
Foo foo = i.getInstance(Foo.class);
assertThat(foo.x, is(true));
}
// EDIT: An example based on the comment by #JeffBowman
#Test
public void memberInjection() {
Foo foo = new Foo();
i.injectMembers(foo);
assertThat(foo.x, is(true));
}
}
If your real world class has a need to mix Guice controlled dependencies with client provided dependencies during construction have a look at assisted inject

Guice: Forcing a binding to be injected as a provider

I'm looking for a way to force certain Guice bindings to be injected as providers only. For example, when there is a configuration like
interface ResultLogger {
void log(String resultAsString);
}
class ResultLoggerProvider implements Provider<ResultLogger> {
// ...
}
class ResultDisplayModule extends AbstractModule {
#Override
protected void configure() {
bind(ResultLogger.class).toProvider(ResultLoggerProvider.class);
}
}
I would like to have way to configure my module so that a class like
#Singleton
class ResultParser {
private final Provider<ResultLogger> loggerProvider;
#Inject
public ResultParser(Provider<ResultLogger> loggerProvider) {
this.loggerProvider = loggerProvider;
}
}
can be injected just fine, but an implementation like
#Singleton
class ResultParser {
private final ResultLogger resultLogger;
#Inject
public ResultParser(ResultLogger resultLogger) {
this.resultLogger = resultLogger;
}
}
should throw a RuntimeException which notifies the developer that ResultLogger is only available via a provider. The exception would ideally be thrown as soon as possible, e.g. during construction of the injector. I'm looking for an easy way to achieve this using the existing API in Guice 3.0.
Maybe you should not implement Provider at all and just have a
#Singleton
public class ResultLoggerProvider {
public ResultLogger get() {...}
// ...
}
#Singleton
class ResultParser {
private final ResultLoggerProvider loggerProvider;
#Inject
public ResultParser(ResultLoggerProvider loggerProvider) {
this.loggerProvider = loggerProvider;
}
}
and remove the other bindings.
I think that it isn't right way. I guess you need smt like
interface ResultLogger {
void log(String resultAsString);
}
class ResultLoggerWrapper implements ResultLogger {
#Inject #Named("day") ResultLogger dayLogger;
#Inject #Named("night") ResultLogger nightLogger;
public void log(String resultAsString){
if(isDay()) {
dayLogger.log(resultAsString)
} else {
nightLogger.log(resultAsString)
}
}
}
bind(ResultLogger.class).to(ResultLoggerWrapper.class);
It should work to bind Provider instead of ResultLogger. That is in your module
bind(new TypeLiteral<Provider<ResultLogger>>(){}).to(ResultLoggerProvider.class);

Categories