Java EE6: Does it matter whether you annotate the interface or bean with #local,#remote? - java-ee-6

I see that in EJB 3 it's desirable to have both local and remote interface.
Then you make a bean that implements these interfaces. Does it matter where the #remote annotation is--either on the interface itself (the first example) or on the bean implementing the interface (the second example)? It is not an issue of just style, is it? Can someone explain the deeper implications?
#Remote
public interface CarSalesRemote {
void getSales();
}
#Stateless
public class CarSales implements CarSalesRemote {
#Override
public void getsales() {}
}
Versus
public interface CarSalesRemote {
void getSales();
}
#Stateless
#Remote
public class CarSales implements CarSalesRemote {
#Override
public void getsales();
}

It's a matter of preference, however, note that when annotating the bean class you have to specify the interface on the annotation #Remote(CarSalesRemote) as stated by the Java EE Tutorial:
The bean class may implement more than one interface. If the bean class implements more than one interface, either the business interfaces must be explicitly annotated either #Local or #Remote, or the business interfaces must be specified by decorating the bean class with #Local or #Remote.
#Remote(InterfaceName.class)
public class BeanName implements InterfaceName { ... }
vs.
#Remote
public interface InterfaceName { ... }

Related

CDI context in Kafka de-/serializer in Quarkus app

I have a Quarkus project with Smallrye reactive messaging based on Kafka. Since I want to work with a "complex pojo" I need a custom de-/serializer.
I'd like to make those two classes CDI beans so I can inject and use my custom logger, which is a CDI bean. Is there a way to achieve this?
Right now my injected logger object is simply null:
import org.apache.kafka.common.serialization.Serializer;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
#ApplicationScoped
public class MySerializer implements Serializer<MyDto>
{
#Inject MyLogger logger;
#Override public byte[] serialize(String topicName, MyDto myDto)
{
// this causes a java.lang.NullPointerException
logger.info("serializing");
...
}
}
As far as I know, you can only register a class name with kafka, and it will create that class internally, ie. without using CDI.
Possible workaround: make the registered object a thin wrapper around the CDI-bean, and delegate the work to the bean:
public class MySerializer implements Serializer<MyDto> {
private MySerializerCdi delegate;
public MySerializer() {
delegate = CDI.current().select(MySerializerCdi.class).get();
}
#Override public byte[] serialize(String topicName, MyDto myDto) {
return delegate.serialize(topicName, myDto);
}
...
}
... and rename your original CDI class accordingly.

Infinite recursion when using subcomponent for encapsulation

I'm trying to achieve encapsulation by using subcomponent which is described here, but I got infinite recursion.
Here is my code:
//tried adding #ScopeA, still the same.
public class A {
#Inject
A(B b) {
}
}
#ScopeA
public class B {
#Inject
B() {
}
}
#Component(modules = AModule.class)
#Singleton
public interface AComponent {
public A a();
}
#Module(subcomponents = SComponent.class)
class AModule {
#Provides
#Singleton
A a(SComponent.Factory factory) {
return factory.component().a();
}
}
#Subcomponent
#ScopeA
interface SComponent {
#ScopeA
A a();
#Subcomponent.Factory
interface Factory {
SComponent component();
}
}
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerAComponent.create().a();
}
}
After checking generated dagger code, I found this:
private final class SComponentImpl implements SComponent {
private SComponentImpl() {}
#Override
public A a() {
return DaggerAComponent.this.aProvider.get();
}
}
It seeems that SComponent are getting A from parent component, which is not what I wanted, where is the problem of my code?
Note that the example from the Subcomponents for Encapsulation page uses a qualifier annotation, #PrivateToDatabase, which is not a scoping annotation and which distinguishes the binding of Database from the binding of #PrivateToDatabase Database.
Subcomponents inherit all of the bindings from their parent components, so you currently do have A available from the parent component and also A available from the subcomponent. This is especially tricky if anything in your subcomponent needs to inject A, if it weren't marked #Singleton: Do you want the A from the parent component, or the A from the subcomponent?
Another tricky part of this situation is that you can't use qualifier annotations on classes that use #Inject constructors.
I'd recommend that you do the following:
Extract an interface from A, so then you have A and AImpl.
Keep your #Provides method that gets an A instance from the subcomponent.
Have the subcomponent expose AImpl, and (to best avoid ambiguity) only inject AImpl in the classes in your subcomponent, not A.
If you'd rather not extract an interface, you could also work around this problem by removing #Inject from A and writing a #Provides method in a module in the subcomponent that returns a qualified A, so the unqualified A goes through the top-level component and the qualified A is only available within the subcomponent.

Jersey EJB injection

I read a lot about the possibility of injection with jax rs 2.0 and in particular with jersey.
I even read that ejb injection is expected in jax rs 2.0 spec. But i still haven't found a unique solution among the variety of posts i read over the net.
In my use case i'm working with:
WildFly 9.0 and Jersey 2.x
I have a webapplication exposing my REST services and importing a jar implementing my model data.
This is the CDI approach:
#RequestScoped
#Path("/myPath")
public class ModelRetriever {
#Context
SecurityContext securityContext;
#Inject
private IMyModel MyModel;
#Path("{i}")
#GET
#Produces("application/json")
public Response countries(#PathParam("i") String countryId)
throws JSONException, Failure, IOException {
MyModel.doSomething();
}
This is my IMyModel interface
public interface IKasPrincipal extends Principal {
public void doSomething();
}
And this is MyModel implementation:
#RequestScope
public class MyModelImpl implements IMyModel {
public void doSomehting() {
doSomething();
}
}
Another method i tried is to use EJB injection changing my previous annotations like this:
#Stateless
#Path("/myPath")
public class ModelRetriever {
#EJB
private IMyModel MyModel;
#Path("{i}")
#GET
#Produces("application/json")
public Response countries(#PathParam("i") String countryId)
throws JSONException, Failure, IOException {
MyModel.doSomething();
}
This is my IMyModel interface
#Local
public interface IKasPrincipal extends Principal {
public void doSomething();
}
And this is MyModel implementation:
#Stateless
public class MyModelImpl implements IMyModel {
public void doSomehting() {
doSomething();
}
}
i get a null object using EJB approach and i get this exception using CDI
Caused by: org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=IMyModel,parent=ModelRetriever,qualifiers={},position=-1,optional=false,self=false,unqualified=null,616459318)
at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:75)
at org.jvnet.hk2.internal.ClazzCreator.resolve(ClazzCreator.java:211)
at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:234)
So is there anything i'm missing?
see other Stack Overflow related posts:
Dependency injection with Jersey 2.0
HK2 Jersey EJB 3 injection
The problem you are having is that HK2 does not know about anything that was not registered directly into it, and HK2 tries to to satisfy all dependency in your Jersey aware class.
I has this issue a while back. Then I discovered that Jersey uses HK2 internally. HK2 is a JSR-330 implementation (CDI).
One would think that a open-source project would declares it's CDI beans and use them regardless of the CDI implementation, but it looks like its not that way.
see : https://java.net/jira/browse/JERSEY-1933
see : https://hk2.java.net/integration.html
You can register your components into HK2...
see : https://jersey.java.net/documentation/latest/ioc.html
For all I know, you cannot inject CDI components (or anything else, as EJB) into Jersey's classes using your own (or your container's) CDI implementation, unless you use Glassfish (which personally I would never use) which in turn uses HK2 as its CDI implementation.
To me, this is a major draw back. But the only(?) draw back of Jersey.
-Maybe I missed something (which is very possible)
-Maybe this is a trick from Oracle so that you can't use Jersey in, let's say, your Websphere app which uses OpenWeb Beans as CDI implementation.
-Maybe they hardwired it to HK2, and just don't care that Jersey can't be used as a drop in component in your application, which relies on CDI or EJB
I'm not aware of why #EJB not worked, but, you can use #Produces/#Disposes bean.
#ApplicationScoped // or some other scoped
public class MyModelProducer {
#Produces public MyModel produceMyModel() {
}
public void disposeMyModel#Disposes final MyModel model) {
}
}

How to safely have a #RestController class implementing an interface annotated with #FeignClient

Given the following code sample
-- client library code
#FeignClient("string-service")
public interface StringClient {
#RequestMapping(method = RequestMethod.GET, value = "/microservicestring")
public String home();
}
#Service
public class StringHystrixClient {
private final SpringClient springClient;
//....
}
-- service library code
#RestController
public class StringController implements StringClient {
public String home(){
return "World";
}
}
#SpringBootApplication
#EnableHystrix
#EnableEurekaClient
#EnableFeignClients
public class StringApplication { ....}
If the service library references the client library, when the application gets started, through component scanning we will get to a state where in filling the dependencies from StringHystrixClient, the spring container will not know what to do because there are two beans implementing StringClient.
One solution to avoid this would be to not implement the StringClient in the StringController, but the code duplication from the interface and the rest controller would be error prone. Can somebody point out a more elegant solution to this problem?

#Inject a Morphia DAO with CDI?

I'm writing a Java EE 6 application that makes use of Morphia to persist objects to MongoDB. I'd like to be able to #Inject my DAO classes where necessary, so I created a Factory class that instantiates the DAO appropriately. It looks something like this:
public class MyDAOFactory {
#Inject
private Datastore mongoDatastore = null;
/**
* Creates the DAO
*/
#Produces
#ApplicationScoped
public MyDAO createDAO() {
MyDAO dao = new MyDAO(
this.mongoDatastore);
return dao;
}
}
The code compiles fine, but when I run my application on JBoss EAP 6.1 it complains because MyDAO does not have a no-arg constructor. I would add one, but the Morphia BasicDAO class does not have one either, so I don't know that it would work that way.
Is there a way to #Inject a DAO instance into my EJB, Servlet, etc.? Or do I need to manually instantiate it every time?
It seems that CDI needs the no-arg constructor for MyDAO for some reason. Maybe because of how you use this bean (see specs ch.5.4 "Client Proxies" for possible reasons).
You cannot create a default constructor, because the base class does not have one and, from what I see from the code the super constructors make immediate use of their args. Therefore passing null to super() from a no-arg constructor will throw errors.
My suggestion is to create an interface (optionally extending org.mongodb.morphia.dao.DAO), e.g. MyDAOInterface that has all public business methods of MyDAO. Then modify MyDAO to implement this interface and change your producer to return MyDAOInterface:
public interface MyDAOInterface extends DAO {...}
public class MyDAO implements MyDAOInterface {
// same implementation
}
public class MyDAOFactory {
#Inject
private Datastore mongoDatastore = null;
/**
* Creates the DAO
*/
#Produces
#ApplicationScoped
public MyDAOInterface createDAO() {
MyDAO dao = new MyDAO(this.mongoDatastore);
return dao;
}
}
By the way, programming to interfaces has the extra benefit of making your code more testable, so it is worth the minor hassle.