Define bean using factory method in plain Java EE - WITHOUT Spring - java

I want to create a bean which can be automatically injected (autowired) by plain Java EE, not with Spring.
The code I have is this:
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
#ApplicationScoped
public class MyConnector {
....
private Client client = ClientBuilder.newClient();
....
}
I'd like to use dependency injection like that instead:
#Inject
private Client client;
In good old Spring I would just define the bean following the guideline http://docs.spring.io/spring/docs/3.1.0.M1/spring-framework-reference/html/beans.html#beans-factory-class-static-factory-method
<bean id="client"
class="javax.ws.rs.client.ClientBuilder"
factory-method="createInstance"/>
and the #Autowired would inject the proper bean.
QUESTION: Can I achieve the same somehow in the plain Java EE without Spring? Can I define a bean in a similar way - and if so, where (in which configuration file)?

You may write your own CDI producer for this purpose
#Dependent public ClientFactory{
#Produces Client createClient() {
return ClientBuilder.newClient();
}
}
Now you are able to use CDI's #Inject to get an instance within your Bean
#ApplicationScoped public class MyConnector {
#Inject private Client client;
}
With those kind of producers, CDI provides an easy-to-use implementation of the factory pattern. You are able to inject nearly everything and everywhere, not only Classes but also Interfaces, other JEE ressources and even primitive types. The injection point do not have to be a class member, but may also be e.g. an argument in a method ...
Each injection will give you a different Proxy, so you are able to inject even more than one Client to your Bean if you have to. If those Proxy objects refer to the same instances or not depends on your implementation of the factory method, but usually you do not want this.

Related

Builder class using Spring services

I would like to create a builder class (i.e. a class implementing the builder design pattern) in a Spring project.
The problem is that I need the builder to use some Spring services.
I obviously don't want the user to explicitly provide the services in the constructor, but when I tried to #Autowire the services, I got Autowired members must be defined in valid Spring bean. I could Annotate my builder with #Component, but that would make it a singleton which will not be desirable for a builder.
How can I inject services to my builder class without making it a singleton?
To use the example from this article, lets say I have the following builder:
BankAccount account = new BankAccount.Builder(1234L)
.withOwner(25324)
.atBranch("Springfield")
.openingBalance(100)
.atRate(2.5)
.build();
I want withOwner to use my UserService to get the actual user from the database given the id number received as a parameter. How would I go about injecting UserService to builder?
There are 2 ways to do that:
1) Put service into withOwner() method
new BankAccount.Builder(1234L)
.withOwner(25324, userService)
2) Add UserService to the Builder and create a builder factory:
#Component
class BuilderFactory {
#Autowire
private UserService user service
BankAccount.Builder newBuilder(Long id) {
return BankAccount.Builder(service, id);
}
}
Usage:
builderFactory.newBuilder(1234L)
.withOwner(25324)
How would I go about injecting UserService to builder?
In your spring bean definitions, you cannot and have not to mix objects managed by Spring and these created by yourself and which Spring is not aware.
While you may make it working but it should be used only in very specific rare cases and generally for legacy/third party dependencies reasons, not in a code where you can change that.
Definitively, you want to inject beans dependencies in beans.
This runtime error message means that you don't respect this rule :
but when I tried to #Autowire the services, I got Autowired members
must be defined in valid Spring bean
About :
I could Annotate my builder with #Component, but that would make it a
singleton which will not be desirable for a builder.
singleton is the default scope but Spring allows you to specify other scopes for a component. Just define it as a prototype bean and it will create a new instance of it at each call.
public class BankAccount{
// ...
#Component
#Scope(value="prototype")
public static class Builder{
//...
}
}

Create proxy for a interface, which could inject by #Autowired, proxy invokes different implement by key parameter

I want to define a annotation like #PlatformRelated, once it is marked in a interface, there will be a proxy bean at spring context, and this proxy bean should be #Priority.I want this proxy could invoke different implement according to key parameter #KeyPrameter.And I still wanna use spring features like #Async,#Trasaction,etc... at my Implement1 and Implement2.
#PlatformRelated
interface MyInterface {
method(#KeyPrameter String parameter);
}
#Component
class Implement1 implements MyInterface {
method(String parameter){
//do something 111
}
}
#Component
class Implement2 implements MyInterface {
method(String parameter){
//do something 222
}
}
#Service
class BusinessService{
#Autowired
private MyInterface myInterface;
public void doSomething() {
myInterface.method("key1");
//Implement1 work
myInterface.method("key2");
//Implement2 work
}
}
Do you guys have some good idea to complete it?
I must admit I haven't totally understood the meaning #Priority, however, I can say that if you want to implement this feature in spring, you should probably take a look at Bean Post Processors.
BeanPostProcessors are essentially a hook to Bean Creation process in spring intended for altering bean behavior.
Among other things, they allow wrapping the underlying bean into the proxy (CGLIB/java.lang.Proxy if you're working with interfaces, or even using programmatically Spring AOP), these proxies can provide a hook to the method execution that can read your annotations (like mentioned #KeyParameter) and execute a code in a way similar to Aspect's code that you already make use of.
Not all bean post processor wrap the bean into the proxy. For example, if you want to implement a BPP that uses "#Autowire", you will return the same bean, just "inject" (read, put by reflection) its dependencies. On the other hand, if you want to implement with BPP #Transactional behavior, then yes, you should wrap the bean into a proxy that would take care of transaction management capabilities before and after the method execution.
It's totally ok to have a spring bean that gets "altered" by many post processors, some of them would wrap it into a proxy other will just modify-and-return the same bean, If there are many BPP-s that wrap the bean into proxy we'll get "proxy inside proxy inside proxy" (you get the idea). Each layer of proxy will handle one specific behavior.
As an example, I suggest you take a look at existing Spring postprocessors, or, for instance, a source code of the following library: Spring Boot metering integration library
This library contains some implementations of post processors that allow metrics infrastructure integration by defining annotations on methods of Spring Beans.

Injecting dependency based on a value in config file

I have a class which takes a configuration interface implementation through DI.
#Inject
private PRCConfiguration prcConfig;
There are various implementations of the PRCConfiguration interface. Currently it is injecting the default implementation. I wish to create a value in a config text file which will define what particular implementation of PRCCOnfiguration to inject.
I wish the #Inject notation to verify what value is in the config file, and based on that inject the particular implementation.
I believe we can annotate different implementation through qualifiers and then inject, such as
#Inject #NewImplementation
private PRCConfiguration prcConfig;
But again i am injecting on compiletime through hard coding.
My config file would be something like
"injectconfig":"NewImplementation"
to inject the #NewImplementation implementation, subsequently if i want a different implementation to be injected. I could just change config file value as
"injectconfig":"DifferentImplementation"
and the different implementation will be injected.
Is what i require possible through CDI?
You can use producer methods to achieve something like that.
Basically you just have to create a CDI bean which a method that returns the correct configuration instance and annotate it with #Produces.
Something like this:
#ApplicationScoped
public class ConfigurationProducer {
#Produces
#ApplicationScoped
public PRCConfiguration getConfig() {
if( someCondition ) {
return new NewConfigurationImpl();
}
else {
return new OldConfigurationImpl();
}
}
}
In this case you should annotated both implementations with #Vetoed or you will get ambiguous dependencies errors. Using #Vetoed on the implementations will tell CDI that using the producer is the only way to obtain PRCConfiguration instances.

Does CDI offer an api for a default producer?

I have a bunch of dependencies written as fast binary web services (aka Ejb3.1). Here is the service delcaration:
#Remote
public interface MyService {...}
You would inject an EJB into a servlet or managed bean with the following syntax:
#EJB
MyService myService;
I don't want to use the #EJB injection however. I'd like to use plain vanilla CDI:
#Inject
MyService myService;
One way to accomplish this would be to Create a #Produces method for every EJB:
#Produces MyService produceMyService(InjectionPoint ijp){
//jndi lookup for MyService interface
}
However, InjectionPoint is capable of giving you all the information you need, such as the target class name (MyService in this case).
Is there a way in CDI to do something like this? I'd want to call this producer last, if the required injection point couldn't be fulfilled in any other manner.
#Produces Object produce(InjectionPoint ijp){
Class ejbInterface = ijp.getType();
//jndi lookup for ejbInterface
}
This is a confusing post, so ask clarification questions. Thanks a ton!
Assuming that I understood your question (see comment): No, there is no API for this.
Good news is that there is a way to achieve this - but you probably don't want to do this at runtime, that's rather a task for application startup.
The CDI extension mechanism offers you some well defined hooks into bean processing at container startup. This is a perfect place for logic that decides about enabling / disabling of certain managed beans (probably based on static classpath information).
Have a look at function and implementation of Seam Solder's #Requires. That should be pretty close to your use case...

how to Inject an EJB into a java class

I want to inject an EJB3 into a java class which is not an EJB.
these classes are both on the same server and application.
Is that possible ...and if yes ..then how ?
Thanks,
Perhaps you should supply more information about your work environment. The usage of CDI changes the whole specturm. You can inject it when you use CDI, otherwise you can only inject it into other EJB's and servlets (if your application server supports it).
Otherwise you can do a lookup using
Context ctx = new InitialContext();
MyEjb ejb = (MyEjb) ctx.lookup("java:comp/env/myEjb");
You can supply a name in the #EJB annotation you supply together with your #Stateless/#Stateful annotation.
#Stateless
#EJB(name="myEjb", beanInterface=MyEjb.class)
public class myEjbImpl implements MyEjb{
// code goes here
}
You can't inject it, but you can make a lookup for that EJB:
Look here:
http://www.roseindia.net/ejb/ejb-lookup.shtml
During the deploymentprocess of your EJB you may see, the Name of your Bean.

Categories