I am using wildfly 10.1.0 and JavaEE 7
I've got this interface:
public interface TestEjb {
String something();
}
and this Ejb class implementing it:
#LocalBean
#Stateless
public class TestEjbImpl implements TestEjb {
#Override
public String something() {
return "Hello world";
}
}
When I am injecting it to my #Path annotated jax-rs class using
#Inject
private TestEjb testEjb;
It gives an error saying "WELD-001408: Unsatisfied dependencies for type TestEjb with qualifiers #Default"
But when I inject it like
#Inject
private TestEjbImpl testEjb;
it works fine.
And which is surprising both ways work with no problems in jboss-eap-6.4. But why?
First of all, you are mixing CDI injection with EJB injection. Rather use #EJB (instead of #Inject) when injecting your EJB.
#LocalBean has a no-interface view. So, you have an interface with no view annotation and a bean with a no-interface view annotation. The EJB Container understands it as a no interface view.
The best way will be to annotate the TestEjb interface with #Local view and remove the #LocalBean from the TestEjbImpl implementation in order for your solution to work.
Interface
#Local
public interface TestEjb {
String something();
}
EJB
#Stateless
public class TestEjbImpl implements TestEjb {
#Override
public String something() {
return "Hello world";
}
}
Injection time
#EJB
private TestEjb testEjb;
I hope this helps.
Further reading...
Related
I want to make some of parts my JEE application independent from others ones using dependency inversion and dependency injection. Below is some code of main core part, that uses MyService, but is independent from other module that should provide implementation of MyService.
public interface MyService {
public void send(MyObject myObject);
}
.
#Stateless
#LocalBean
public class MyServiceWrapper implements MyService {
#Inject
private MyService myService;
#Override
public void send(MyObject myObject) {
myService.send(myObject);
}
}
To clarify:
Module A contains classes:
MyObject,
MyService,
MyServiceWrapper,
Module B contains implementation of MyService.
I want MyServiceWrapper to have injected implementation of MyService provided by module B, so module A can call implementation of MyService by using MyServiceWrapper, but in te same time module A is independent from module B.
The problem with above code, is that container do not know which implementation of MyService should be injected.
How it should be written so MyServiceWrapper, so it won't be injected to itself, but proper implementation (provided in other module) will be injected instead?
The correct way would be to use what is known as a Qualifier , one example from CDI would be the annotation #Named, this would get rid of ambiguity for the container.
public interface MyService {
void send(MyObject myObject);
}
and the implementation of MyService :
#Named("fromModuleA")
#ApplicationScoped
public class MyServiceWrapper implements MyService {
#Inject
#Named("fromModuleB")
private MyService someOtherBean;
#Override
public void send(MyObject myObject) {
this.someOtherBean.send(myObject);
}
}
#Named("fromModuleB")
#ApplicationScoped
public class SomeOtherBeanFromModuleB implements MyService{
#Override
public void send(MyObject myObject) {
// implementation
}
}
The #Inject comes from a Java specification called CDI (Context and Dependency Injection), with this annotation it doesn't matter whether you use it on EJBs or CDI beans, but #EJB will only work with the EJB Container. Also note you don't really need the Interface MyService at least not anymore but it's a good practice to code to the interface.
I have an abstract bean with injected ISomeOtherBean interface:
public abstract class AbstractBean {
#EJB ISomeOtherBean myService;
}
The ISomeOtherBean is interface. He have many implementations, for example: SomeBeanA, SomeBeanB...
#Stateless
public class SomeBeanA implements ISomeOtherBean {
}
#Stateless
public class SomeBeanB implements ISomeOtherBean {
}
How can I inject concrete implementation of ISomeOtherBean inside some implementation of the AbstractBean?
#Stateless
public class BeanImpl extends AbstractBean {
// how write that I want inject SomeBeanB which implements ISomeOtherBean
}
First i tried to inject concrete implementation inside BeanImpl, then I passed it to additional method of superclass (Abstractbean) which writed it to field myService.
But this solution is bad for me. I remember Spring has ability to pass some beans to constructor of given bean. But it was inside XML configuration. I want something like this, but with EJB and annotation configurations.
Anyone knows how do it?
I have the following situation:
During the configuration/startup of Spring Boot, I am picking up a list of interfaces using reflections. These interfaces are replaced with a proxy implementation (using java.lang.reflect.Proxy, because I cannot use Spring's AOP). This is working.
There is a super and the actual interface. So I have something like this:
public interface Stream{
}
public interface ExampleStream extends Stream{
doAction();
}
Now I want to use the interfaces in other beans unsing #Inject, e.g.
#Service
public class MyService{
#Inject
private ExampleStream exampleStream;
public void fooBar(){
exampleStream.doAction();
}
}
And there is the method to initialize the proxy:
...
StreamInvocationHandler invoHandler = ... // this implements InvocationHandler (the proxy)
ClassLoader cl = ClassUtils.getDefaultClassLoader();
Class<? extends Stream> stream = ... // fetch the class, which is ExampleStream.class
Object impl = Proxy.newProxyInstance(cl, new Class[]{stream}, invoHandler);
ExampleStream exampleStream = (ExampleStream)impl;
// this is working
exampleStream.doAction();
The mechanism should be equal to the spring data repositories (except of the #Repository annotation and so on...)
But now, I don't know how to inject. Because of some SO answers, I tried to implement ApplicationContextAware as follows:
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
... // stuff from above
AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
beanFactory.autowireBean(impl);
beanFactory.initializeBean(impl, "exampleBean");
}
This did not work (field exampleStram in myservice has no qualifying bean...). I also tried another suggestion with a similar solution using BeanDefinitionRegistryPostProcessor, but this is only intended for bean definitions.
Where and how can I inject those kinds of self created beans?
I try to make a little test with versioning a soap service.
My idea was that the business logic always implement the newest version and a soap service provide its functionality. To support the older version of the interface I want to map the jaxb classes via mapping framework to the newer version and then call the endpoint implementation from the older endpoint. So in endpoint v1 I inject the endpoint v2 and call it from there. But it seems, that neither cdi nor ejb injection works:
#Stateless
#WebServiceProvider(serviceName = "WebserviceV1", wsdlLocation = "META-INF/wsdl/My.wsdl", targetNamespace = "http://smitch.ch/service/v1", portName = "ServicePortV1")
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class ServiceImplV1 implements ServicePortV1 {
private ModelMapper modelMapper = new ModelMapper();
#Inject
private ServiceImplV2 v2;
#PostConstruct
void configureMapping() {
PropertyMap<v1.RequestType, v2.RequesType> specialCase = new PropertyMap<>() {
protected void configure() {
//...
}
};
modelMapper.addMappings(specialCase);
}
#Override
public v1.ResponseType service(v1.RequestType soapRequest) {
v2.RequestType v2Request = map(soapRequest, v2.RequestType.class);
return map(v2.service(v2Request), v1.ResponseResponse.class);
}
}
The version 2 endpoint is defined more or less the same way, but has implemented the business logic in the body.
I always get the error
WELD-001408 Unsatisfied dependencies for type [ServiceImplV2] with qualifiers [#Default] at injection point [[field] #Inject private v1.ServiceImplV1.v2]"}}
I use JBoss EAP 6.3.
Is there some special behaviour in handling webservice endpoints?
Here some more information. Both classes are in the same package and yes, I have a beans.xml.
V2 looks like:
#Stateless
#WebServiceProvider(serviceName = "WebserviceV2", wsdlLocation = "META-INF/wsdl/MyV2.wsdl", targetNamespace = "http://smitch.ch/service/v2", portName = "ServicePortV2")
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class ServiceImplV2 implements ServicePortV2 {
#Inject
private Processor processor;
#Override
public v2.ResponseType service(v2.RequestType soapRequest) {
return processor.process(soapRequest);
}
As Jan mentioned, try adding #LocalBean to the ServiceImpleV2 to add a no-interface view. Then you should be able to injet your webservice with #EJB or #Inject.
#Stateless
#LocalBean
#WebServiceProvider(serviceName = "WebserviceV2", wsdlLocation = "META-INF/wsdl/MyV2.wsdl", targetNamespace = "http://smitch.ch/service/v2", portName = "ServicePortV2")
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class ServiceImplV2 implements ServicePortV2 {
#Inject
private Processor processor;
#Override
public v2.ResponseType service(v2.RequestType soapRequest) {
return processor.process(soapRequest);
}
I am learning Java EE CDI, dependency injection, and #Produces in particular. I am wondering why in getGreedingCard() method, it needs a #Produces annotation at all, since the two classes GreetingCardImpl and AnotherGreetingCardImpl are already imported into the space. This is just like the regular package/class dependency and a simple import solves the problem. Why does it need a dependency injection through a #producer annotation?
Thanks for explanation in advance.
public interface GreetingCard {
void sayHello();
}
public class GreetingCardImpl implements GreetingCard {
public void sayHello() {
System.out.println("Hello!!!");
}
}
public class AnotherGreetingCardImpl implements GreetingCard {
public void sayHello() {
System.out.println("Have a nice day!!!");
}
}
import com.javacodegeeks.snippets.enterprise.cdibeans.impl.AnotherGreetingCardImpl;
import com.javacodegeeks.snippets.enterprise.cdibeans.impl.GreetingCardImpl;
#SessionScoped
public class GreetingCardFactory implements Serializable {
private GreetingType greetingType;
#Produces
public GreetingCard getGreetingCard() {
switch (greetingType) {
case HELLO:
return new GreetingCardImpl();
case ANOTHER_HI:
return new AnotherGreetingCardImpl();
default:
return new GreetingCardImpl();
}
}
}
I am wondering why in getGreedingCard() method, it needs a #Produces
annotation at all, since the two classes GreetingCardImpl and
AnotherGreetingCardImpl are already imported into the space.
Well, it's not that getGreetingCard needs the #Produces annotation. The point is to enable other classes to recieve GreetingCards via Dependency Injection.
public class Foo {
#Inject // <--- will invoke #Producer method
GreetingCard foosGreetingCard
...
}
See here for more details:
A producer method is a method that acts as a source of bean instances.
The method declaration itself describes the bean and the container
invokes the method to obtain an instance of the bean when no instance
exists in the specified context.
In your case it doesn't need #Produces as you will be injecting factory bean and using its method directly to create instances, and not injecting the greetingCard beans themseleves.
#Inject
GreetingCardFactory factory;
...
GreetingCard card = factory.getGreetingCard();
If you would define it as #Produces method, and the try to inject GreetingCard, then you would get exception that I've described in the comment.
However, if you would additionally create qualifier, like this:
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
public #interface ProducedCard {}
and add it to the producer method:
#Produces #ProducedCard
public GreetingCard getGreetingCard() {
...
then you would be able to inject just GreetingCard beans using your producer method like this:
#Inject #ProducedCard
GreetingCard card;
since now there is no ambiguity, as there is only one place to create greeting cards marked with #ProducedCard :-)