Does CDI offer an api for a default producer? - java

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...

Related

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.

Bean both an EJB and JX-RS resource

In terms of objects created at run time by the application server, what is the difference between
making of a bean both an EJB and a JAX-RS resource
#Stateless
#Local
#Path("current")
public class Facade
{
#PersistenceContext
EntityManager entityManager;
#EJB
...
// methods
}
using two different beans
#Path("current")
public class Facade
{
#EJB
private MyEjb myEjb;
// methods
}
#Stateless
#Local
public class MyEJB
{
// methods
}
Thanks for your answers!
EDIT:
ahah maybe my real questions would be about what's the result of using jax-rs annotations on an EJB, but that' basically the same question I asked.
It works. But if we stick to Oracle specification, exposing an EJB as a Web Service (rest or soap) is a kind of quick solution, with you promising to revisit this approach in the nearest future :-)
Infact, again sticking to what Oracle say, the EJB should reside on the business layer, and the web service should be in the integration layer.
I am not arguing that exposing an EJB is a wrong approach, but just because it is quite easy to develop rest service in Java, I would create a façade class, and transform in a service. Then I would inject the EJB into the class, or by jndi lookup if it is a rest. To have better separation of concerns.
This way you don't end up with a single class stuffed with annotation, but you are introducing flexibility, and have an architecture that may evolve, for example maybe you can decide in the future to deploy the business layer on a dedicated machine...whatever.

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

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.

How do I refactor my servlet to take advantage of dependency injection?

I'm using Tomcat 6.0.33 with Java 6. I have this servlet ...
public class SaveXmlServlet extends HttpServlet {
private CacheService cacheService;
public void init(ServletConfig config) throws ServletException {
cacheService = CacheServiceLocator.cacheService();
} // init
How can I redesign my servlet to ...
Take advantage of dependency injection so that a mocking framework like mockito can inject its own "cacheService" implementation
Guarantee that there is only one instance of cacheservice in my jvm. Right now the line "CacheServiceLocator.cacheService()" guarantees this.
? I'm not using (or allowed to use) frameworks like Spring or Guice. Grateful for any thoughts on refactoring this. Thanks, - Dave
There are a few options, although I recommend smacking someone for not "letting" you use a framework. Two quickies; I'm sure there are others. I'd go the smacking route first.
You can mock static classes using a combination of EasyMock/Mockito and, say, PowerMock. Technically you don't need to change anything at all to get the in-test behavior you want.
A class name provided by a servlet init parameter or JNDI resource could be used to create an instance of the cache locator. Providing a setter for the same allows a unit/etc. test to set it on the class.

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