I've made a mavenized web application with spring, spring security... Now, I want to add ejb module for database access, I was looking on the internet but I didn't find something clear because it's my first time with EJB.
I want to use something like #EJB in my controller
like"
#Stateless(name = "CustomerServiceImpl")
public class CustomerServiceImpl implements CustomerService
#EJB
private MyEjb myEjb;
and how can I configure it in spring context if there is a tutorial or any other help. It will be great and thank you
To inject your ejb 3 bean in spring bean you can follow below steps.
1. Create your Spring bean
2. Create your EJB with its Remote and Local Interface
3. Write Implementations class
e.g.
package com.ejb;
#Local
public interface MyEjbLocal{
public String sendMessage();
}
package com.ejb;
#Remote
public interface MyEjbRemote{
public String sendMessage();
}
#Stateless(mappedName = "ejb/MessageSender")
public class MyEjbImpl implements MyEjbLocal, MyEjbRemote{
public String sendMessage(){
return "Hello";
}
}
above is the example of EJB3 which uses both remote and local interface
Now we create the Spring bean in which we inject this ejb.
package com.ejb;
#Service
public class MyService {
private MyEjbLocal ejb;
public void setMyEjbLocal(MyEjbLocal ejb){
this.ejb = ejb;
}
public MyEjbLocal getMyEjbLocal(){
return ejb;
}
}
We have added the instance of ejb in spring however we need to inject this in spring's spring-config.xml.
There are 2 ways to inject the ejb in spring bean
First Way
<bean id ="myBean" class="org.springframework.ejb.access.LocalStetelessSessionProxyFactoryBean">
<property name="jndiName" value="ejb/MessageSender#com.ejb.MyEjb=Local />
<property name="businessInterface" value="com.ejb.MyEjbLocal" />
</bean>
Note: I have used the Local interface here you can use Remote as per your need.
Another way of injecting the ejb is
<jee:remote-slsb id="messageSender"
jndi-name="ejb/MessageSender#com.ejb.MyEjbLocal"
business-interface="com.ejb.MyEjbLocal"
home-interface="com.ejb.MyEjbLocal"
cache-home="false" lookup-home-on-startup="false"
refresh-home-on-connect-failure="true" />
So when the bean get initialized at that time the ejb will get injected in your spring bean.
Have a look here: http://docs.spring.io/spring/docs/4.1.0.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#ejb-access-local
You can inject EJB using setter injection. Configure your bean this way:
<bean id="myComponent" class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<property name="jndiName" value="ejb/myBean"/>
<property name="businessInterface" value="com.mycom.MyComponent"/>
</bean>
<bean id="myController" class="com.mycom.myController">
<property name="myComponent" ref="myComponent"/>
</bean>
You can also use <jee:local-slsb> tag to be able to inject your EJB:
<jee:local-slsb id="myComponent" jndi-name="ejb/myBean"
business-interface="com.mycom.MyComponent"/>
<bean id="myController" class="com.mycom.myController">
<property name="myComponent" ref="myComponent"/>
</bean>
Related
I have a prototype Bean which is instantiated by singleton bean with a Provider:
#Component
#Scope("prototype")
class MyPrototype {}
#Component
class MySingleton {
#Autowired
javax.inject.Provider<MyPrototype> prototypeFactory;
}
This works fine, but our company rules state that #Autowired is not allowed; the common pattern is #Resource(SingletonBeanClass.BEAN_ID).
Is it possible to annotate the Provider this way so the Spring lookup can create it?
I'm aware I can add a factory method with #Lookup, or a singleton factory bean, but I prefer the Provider.
EDIT:
I didn't get it to work this way and in the end had to edit spring.xml; see below for details.
As you have an XML configuration file, you can configure it via XML in the following way:
<bean id="myPrototype" class="some.package.MyPrototype" scope="prototype" />
<bean id="mySingleton" class="some.package.MySingleton">
<lookup-method name="getPrototypeFactory" bean="myPrototype "/>
</bean>
In this way, you have to access to the myPrototype with the getPrototypeFactory() and not directly to the property. You can even remove the annotations on those 2 classes.
For any extra details, you can look at the following blog post Injecting a prototype bean into a singleton bean
For reference, if someone comes across this via Google:
I ended up needing to declare it in the spring.xml. I tried #Lookup, but even that didn't work due to the prototype-bean referencing yet another prototype-bean.
This is how it was recommended here,
but it does not work:
#Component("proto1")
#Scope("prototype")
class MyPrototypeBean1 {
#Lookup(value="proto2")
protected MyPrototypeBean2 createBean2() { return null; }
}
#Component("proto2")
#Scope("prototype")
class MyPrototypeBean2 {
}
#Component("singleton")
class MySingleton {
#Lookup(value="proto1")
protected MyPrototypeBean1 createBean1() { return null; }
}
This results in the error message "Cannot apply #Lookup to beans without corresponding bean definition" when trying to create "innerBean...".
I assume it is due to "lookup methods cannot get replaced on beans returned from factory methods where we can't dynamically provide a subclass for them" as is quoted in the link above.
So what I ended up doing in the spring.xml:
<bean name="proto2" class="my.package.PrototypeBean2" />
<bean name="proto1" class="my.package.PrototypeBean1" >
<lookup-method name="createBean2" bean="proto2" />
</bean>
<bean name="singleton" class="my.package.SingletonBean" >
<lookup-method name="createBean1" bean="proto1" />
</bean>
And this works.
For the unit tests, I had to subclass the respective classes:
class SingletonUnitTest {
#Mock
MyPrototypeBean1 bean1;
#InjectMocks
DummySingleton sut;
#Before public void setBean1() {
sut.bean = bean1;
}
static class DummySingletonBean extends MySingeton {
MyPrototypeBean1 bean;
protected MyPrototypeBean1 createBean1() {
return bean;
}
}
}
I am using Hazelcast 2.6 with Spring. Currently I have entry listener configured using spring-hazelcast configuration. For method entryEvicted I want to call method of my spring bean. Is it possible to inject that bean via xml configuration (or annotation) where is my entry listener configured.
Here is sample code of my entry listener.
public class HazelcastSessionMapEntryListener implements EntryListener<String,SessionMapEntry>{
private CustomBean customBean;
#Override
public void entryEvicted(EntryEvent<String, SessionMapEntry> event) {
customBean.method(event);
}....}
I am wondering is it possible to have instance of customBean injected without calling application context getBean method from my code.
In Hazelcast you can configure a spring bean as a listener and configure that bean how ever you like. Here is a sample for your case;
<hz:listeners>
<hz:listener implementation="entryListener"/>
</hz:listeners>
<bean id="entryListener" class="com.acme.EntryListener">
<property name="customBean" ref="customBean" />
</bean>
<bean name="customBean" class="com.acme.CustomBean"/>
Background:
I am using programmatic authentication (basic authentication) using java security.
I have a Stateless session bean(EJB 3). I can inject the Sessioncontext to get the security Principal, to get the user name.
In the same project I am using spring beans for JDBC and Aspect. I want to get the user name in one of the aspect(Audit) which is also a spring bean.
Question:
Is it possible to access the ejb sesssioncontext in the Spring bean. If so how to do that?
If no, how can the username be accessed from the Spring bean which is also an aspect.
Thanks,
Amit
This can be done by injecting the EJB into the spring bean. You can do it through a manual JNDI lookup (like you would in any other EJB Client) or use Spring's JndiObjectFactoryBean. With Spring's JndiObjectFactoryBean:
Inject the SessionContext into the EJB
#Resource
private SessionContext ctxt;
//getter and setter
Configure the factory bean in your bean configuration file. postageService being the EJBRef we're interested in (Configuration poached from Apress Spring Recipes)
<bean id="postageService class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiEnvironment">
<props>
<prop key="java.naming.factory.initial">
org.apache.openejb.client.RemoteInitialContextFactory
</prop>
<prop key="java.naming.provider.url">
ejbd://localhost:4201
</prop>
</props>
</property>
<property name="jndiName" value="PostageServiceBeanRemote"/>
</bean>
Wire the ejb reference into your spring bean
public class PostalServiceClient{
//wired EJB
private PostageService service;
//getter and setter
private SessionContext retrieveSessionContext(){
service.getCtxt(); //get the SessionContext from the EJB injection
}
}
kolossus, Thanks for the reply.
There is another way that I could found. Following is the Link to the previous post. So basically I did exactly the same thing :
1) Added the following line to the spring-context xml
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
<property name="alwaysUseJndiLookup" value="true" />
</bean>
2) Added following line to the my spring bean to access the EJB's session context
#Resource(mappedName = "java:global/TopoServices/MessageRestService!com.myrest.MessageRestService")
private MessageRestService myBean;
Important thing is Jboss 7.1 does not support custom jndi any more unlike Jboss 5 so I used the default jndi.
I think this is more cleaner way to address my requirement.
I have a scenario for example.
<bean id="xyzService" class="XyzServiceImpl" scope="prototype">
<property name="aDependency" ref="aDependency" />
<property name="bDependency" ref="bDependency" />
</bean>
<bean id="useService" class="UseServiceImpl">
<property name="xyzService" ref="xyzService"/>
</bean>
Java Class :
public class XyzServiceImpl implements XyzService{
private ADependency aDependency= null;
private BDependency bDependency= null;
// getters and setters...
}
public class UseServiceImpl implements UseService {
private XyzService xyzService= null;
// getters and setters...
xyzService.doSomething();
}
Now every time inside the UseServiceImpl I expect a new Instance of xyzService, but i always return the same singleton instance. Also there is a scenario that the aDependency and bDependency may internally have again some more references to other beans.
Now I have a question like how do I get an new Instance of xyzService. Am I doing something wrong?
By default scope of spring bean is singleton , You need to mark the scope prototype to instruct spring
<bean id="beanId" class="some.class.Name" scope="prototype"/>
Spring will create new instance on each request of Bean
See
bean scopes
I could easily find the solution by implementing the ApplicationContextAware Interface which has the getter and setter method for context. From the context I can say getBean and get the new Instance
public class UseServiceImpl implements UseService,ApplicationContextAware {
private ApplicationContext context;
XyzService xyzService= context.getBean(XyzServiceImpl.class);
// getter and setter for applicationContext
private XyzService xyzService= null;
// getters and setters...
xyzService.doSomething();
}
If you have the following:
<bean id="xyzService" class="XyzServiceImpl" scope="prototype">
<property name="aDependency" ref="aDependency" />
<property name="bDependency" ref="bDependency" />
</bean>
<bean id="useService1" class="UseServiceImpl">
<property name="xyzService" ref="xyzService"/>
</bean>
<bean id="useService2" class="UseServiceImpl">
<property name="xyzService" ref="xyzService"/>
</bean>
Then you should be able to verify that the xyzService property for useService1 and useService2 do contain different instances of xyzService. That's the effect of declaring xyzService to be scoped as a prototype. If you really want new instances of the xyzService bean to be available during the lifetime of the useService bean, I think you'll need a different approach - take a look at the documentation for Method injection.
In your example, every time you request spring container an instance of userService, it will return the singleton instance and injecting a new instance of xyzService.
However, when spring creates a new instance of xyzService, it will use the singleton instance of aDependency and bDependency unless otherwise they are also defined as prototype.
I have a session scoped bean defined like so:
<!-- this is where the serviceImpl bean is defined -->
<import resource="classpath:META-INF/*-core-context.xml"/>
<bean id="myBean" class="com.company.Bean">
<property name="service" ref="serviceImpl"/>
</bean>
Now inside the bean I have defined a default value for the injected service like so:
public class Bean {
private Service service = new NullService();
public void setService(Service service) {
this.service = service;
}
}
What I want to do is to provide the ability to optionally inject the service and if you choose not to the Bean will use the NullService implementation which simply does nothing, not affecting the bean logic in any way.
The problem is that for some reason the serviceImpl is never injected and I always end up with the NullService implementation.
So is there some spring setting or feature which prevents it from injecting it ? Or do you have any other ideas on why this might happen ?
More info
This is the setter that spring uses to inject the service:
public void setPermissionsService(PermissionService permissionsService) {
this.permissionsService = permissionsService;
System.out.println("setting permissions service to: " + permissionsService.getClass().getName());
if (this.permissionsService instanceof NoopPermissionsServiceImpl) {
System.out.println("NULL IMPLEMENTATION");
}
else if (this.permissionsService instanceof PermissionServiceImpl) {
System.out.println("CORRECT IMPLEMENTATION");
}
else {
System.out.println("WHAT ?!?!");
}
}
It prints "WHAT ?!?!".
So it turns out spring sets it to a dynamic proxy $Proxy859. Is there a way to see the class the proxy is proxying ?
You seem to be lacking a definition for your serviceImpl bean in your configuration. Something like
<bean id="serviceImpl" class="com.company.ServiceImpl" />
The only solution I see to your problem is to reverse-engineer this a bit. Do something like that in the same spring.xml:
<bean id="myBean" class="com.company.Bean">
<property name="service" ref="testServiceImpl"/>
</bean>
<bean id="testServiceImpl" class="com.company.TestServiceImpl" />
Then implement the TestServiceImpl with simple debug messages indicating that construction and your service call is actually working. This has to work. If it does you have a problem with your original service definition. If not you have a problem in your Bean.
Try to narrow the problem to a simpler. And then work into the simpler problem.
Good luck!
Instead of using instanceof use Class.isAssignableFrom(Class)