I have a requestScope bean, regular Java bean, and Spring configuration just like the code shown below. May I know how can I access the bean's property from regular Java code that is configured with Spring?
Managed Bean
#ManagedBean(name="requestBean")
public class RequestBean {
private String theID;
/** getter and setter of theID **/
}
Spring Bean
public class SpringBean {
private RequestBean theBean = null;
// how could I access the RequestBean.theID from this class ??
}
Spring configuration
<bean id="springBean" class="org.huahsin.SpringBean"/>
Maybe I do not understand the question, but I think it is simply by calling the getter:
public class SpringBean {
private RequestBean theBean = null;
...
public void aCallingMethod() {
if (theBean != null) {
theBean.getTheId(); // <-- here it is !!
}
}
}
EDIT
To inject the request bean into the Spring bean, either you use an #Autowired annotation:
public class SpringBean {
#Autowired
private RequestBean theBean = null;
...
}
Either you inject it in your XML file:
<bean id="springBean" class="org.huahsin.SpringBean">
<property name="theBean" ref="requestBean"/>
</bean>
Related
I'm trying to pass parameter to one of constructor of my BBFilter component, however it throws the exception that No beans of String type found. I have autowired the constructor as well. Am I doing anything wrong? Please advise
#Bean
public MyBean bbFilter() {
BBBean bbBean = new BBBean();
bbBean.setFilter(new BBFilter("plan1"));
}
BBFilter
#Component
public class BBFilter implements Filter {
private String planType;
#Autowired
public BBFilter(String planType) { --> Could not autowire. No beans of String type found
this.planType = planType;
}
}
I am assuming you are using Spring. The #Component annotation tells spring to automatically create an Instance of BBFilter as a Bean.
You also annotated the constructor with #Autowired. So Spring searches it's beans for fitting types and injects the automatically on construction. Since you probably didn't define any String bean it cannot autowire the String and throws an exception.
But since you want to create the Filter manually anyways you can simply remove both annotations from your BBFilter Class:
public class BBFilter implements Filter {
private String planType;
public BBFilter(String planType) {
this.planType = planType;
}
}
This should fix the exception but you also can no longer inject it anywhere else (per #Autowire) if needed.
Declare bean of BBFilter like
#Bean
public BBFilter bbFilter() {
return new BBFilter("plan1");
}
And use it in BBBean like this
#Bean
public MyBean bbFilter() {
BBBean bbBean = new BBBean();
bbBean.setFilter(bbFilter());
}
And remove #Component and #Autowired from BBFilter
this is simple question,
how to get servlet context parameter when spring instantiate the bean?
my servlet context xml
<beans:bean id="ApplicationInfo" class="xx.xx.xx.ApplicationInfo"/>
In my code
public class ApplicationInfo{
ApplicationInfo()
{
//get context.xml or web.xml parameter
String xxx = .......;
}
}
my pom.xml
<org.springframework-version>3.2.11.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.9</org.aspectj-version>
<org.slf4j-version>1.5.10</org.slf4j-version>
<org.springsecurity-version>3.2.5.RELEASE</org.springsecurity-version>
<org.springjpa-version>1.1.0.RELEASE</org.springjpa-version>
<hibernate.version>4.1.6.Final</hibernate.version>
<postgresql.version>9.1-901-1.jdbc4</postgresql.version>
<tiles-version>2.2.2</tiles-version>
<jackson-json-version>2.1.0</jackson-json-version>
Note: i tried to get servlet context by using #annotation ,however it is nullpointer.
If you want to access autowired bean in constructor, you have to use constructor type injection:
#Component
public class ApplicationInfo {
private final FooService fooService;
#Autowired
public ApplicationInfo(ServletContext servletContext, FooService fooService) {
this.fooService = fooService;
// do something here
}
}
If you have to (or want to) stick to XML beans definition you've got to make your class implement ServletContextAware interface, which makes Spring automatically set this dependency through setter. Instead of accessing it in constructor, you do it in method annotated with #PostConstruct which is fired when bean is fully initialized:
public class ApplicationInfo implements ServletContextAware {
private final FooService fooService;
private ServletContext servletContext;
public ApplicationInfo(FooService fooService) {
this.fooService = fooService;
}
#PostConstruct
public void init() {
// now you fooService and servletContext are set
}
#Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
}
<bean class="demo.ApplicationInfo">
<constructor-arg name="fooService" ref="fooService" />
</bean>
<bean id="fooService" class="demo.FooService"/>
Try with #Value annotation
public class ApplicationInfo {
#Value("${parameterName}")
private String parameter;
}
I have a problem to select the correct spring bean that should get injected.
I need a way to tell the spring container what bean to inject depeding on the call to a previous class. I do all the spring bean wiring in xml.
My question: is this possible and if it is any reference on an implementation?
I have created some sample code to illustrate what i´m trying to accomplish. Feel free to change it so that it will work to get the correct ReportHeader bean injected depending on the selected reportType during runtime.
public enum ReportType{
Credit,
Annul
}
public class ReportService {
private ReportHeaderService reportHeaderService;
private ReportType reportType;
public ReportService (){}
public setReportType(ReportType reportType){
this.reportType = reportType;
}
public void setReportHeaderService(ReportHeaderService reportHeaderService){
this.reportHeaderService = reportHeaderService;
}
private void generateHeader(){
//i would like to call my service like this and have the correct bean injected to ReportHeader.
reportHeaderService.generateHeader(reportType)
}
}
public class ReportHeaderService {
private ReportHeader reportHeader;
//this will call the injected bean that needs to be selected accoring to the ReportType
public void generateHeader(ReportType type){
reportHeader.createHeader();
}
}
public interface ReportHeader{
public void createHeader();
}
public class CreditReportHeader implements ReportHeader{
public void createHeader(){
..dostuff();
}
}
public class AnnulReportHeader implements ReportHeader{
public void createHeader(){
..dostuff();
}
}
Consider injecting a Map<ReportType, ReportHeader> to ReportHeaderService, so that generateHeader works as:
public class ReportHeaderService {
private Map<ReportType, ReportHeader> reportHeaderMap;
public void generateHeader(ReportType type){
ReportHeader reportHeader = reportHeaderMap.get(type);
if (reportHeader != null) {
reportHeader.createHeader();
}
}
}
You can define a ReportHeaderFactory to get the ReportHeader according to ReportType:
public class ReportHeaderFactory {
private CreditReportHeader creditReportHeader;
private AnnulReportHeader annulReportHeader;
public ReportHeader getReportHeader(ReportType reportType) {
switch (reportType) {
case Credit:
return creditReportHeader;
case Annul:
return annulReportHeader;
default:
throw new IllegalArgumentException("No Such Header");
}
}
}
Re-define the ReportHeaderService with an instance of ReportHeaderFactory:
public class ReportHeaderService {
//private ReportHeader reportHeader;
private ReportHeaderFactory headerFactory;
//this will call the injected bean that needs to be selected accoring to the ReportType
public void generateHeader(ReportType type){
//reportHeader.createHeader();
headerFactory.getReportHeader(type);
}
}
As you are doing all the spring bean wiring in xml, you just need to make below entries in the config file:
<bean id="ReportHeaderService" class="x.y.ReportHeaderService">
<property name="headerFactory" ref="headerFactory" />
</bean>
<bean id="headerFactory" class="x.y.ReportHeaderFactory">
<property name="creditReportHeader" ref="creditReportHeader" />
<property name="annulReportHeader" ref="annulReportHeader" />
</bean>
<bean id="creditReportHeader" class="x.y.CreditReportHeaderImpl" />
<bean id="annulReportHeader" class="x.y.AnnulReportHeaderImpl" />
I'm used to using Spring to do my dependency injection like so:
<context:component-scan base-package="org.emmerich.myapp" />
and then annotating my dependent classes with Autowired like so:
public class DependentClass {
#Autowired
private Dependency dependency;
}
However, with the changes in Hibernate 4.0, we're now advised to use the new Integrator interface for service discovery. This includes adding event listeners for triggers such as postUpdate, postDelete etc.
Unfortunately, this doesn't play nicely with dependency injection through annotated dependencies. I have the following setup:
An integrator I have defined to add my listener to the ServiceFactory. This is referenced in the file META-INF/services/org.hibernate.integrator.spi.Integrator.
public class MyIntegrator implements Integrator {
private MyListener listener;
public MyIntegrator() {
listener = new MyListener();
}
#Override
public void integrate(Configuration configuration,
SessionFactoryImplementor sessionFactory,
SessionFactoryServiceRegistry serviceRegistry) {
final EventListenerRegistry eventRegistry =
serviceRegistry.getService(EventListenerRegistry.class);
eventRegistry.prependListeners(EventType.POST_COMMIT_INSERT, listener);
}
I also have defined the class MyListener, which looks like your typical event listener.
#Component
public class MyListener implements PostInsertEventListener {
#Autowired
private Dependent dependent;
public void onPostInsert(PostInsertEvent event) {
// dependent == null
}
}
Unforunately, as shown by the comment, this doesn't work. I guess it's because I'm instantiating MyListener inside MyIntegrator, it doesn't pick up the component and doesn't autowire components. However, if I try this:
#Component
public class MyIntegrator {
#Autowired
private MyListener listener;
...
}
Then the listener isn't autowired.
Firstly, it feels wrong whilst using Spring to have to do new MyListener(). I expect to be able to define that as an autowired dependency and have Spring create a singleton for me. My question is this:
What's the best approach to using dependency injection with the new Integrator interface? The Integrators are used to build a SessionFactory, and so when they're asked to integrate themselves I guess there isn't an application context available. Because of that, any beans I require in the Integrator need to be created the "old fashioned" way and won't receive the autowiring on them.
I'm quite new to the world of Spring, would you say this is something that I should expect to see? I understand that I'm in a different scope of the application when I'm in the SessionFactory, but is there a way to obtain a reference to the bean and enable autowire even though I'm creating it via new?
The solution I came up with used ApplicationContextAware. It meant that MyListener received a reference to the ApplicationContext whenever the context was available, and I referenced the beans from the context on method calls, rather than on bean construction. Creating a bean with new doesn't limit this, so Spring still gives me the application context:
#Component
public class MyListener implements PostInsertEventListener, ApplicationContextAware {
private static ApplicationContext context;
public void onPostInsert(PostInsertEvent event) {
// getDependent() == correct!
}
public void setApplicationContext(ApplicationContext context) throws BeanException {
this.context = context;
}
public Dependent getDependent() {
return context.getBean(Dependent.class);
}
}
Is there a better way?
As stated in the comment i went another way of integrating Spring managed HibernateEventListeners. Here's the code:
The identifier interface for Spring managed Hibernate event listeners:
public interface HibernateEventListener { }
The HibernateIntegrator:
#Service
public class HibernateSpringIntegrator {
private static final Logger log = LoggerFactory.getLogger(HibernateSpringIntegrator.class);
#Autowired
private HibernateEntityManagerFactory entityManagerFactory;
#Autowired
private HibernateSpringIntegratorRegistry hibernateSpringIntegratorRegistry;
#PostConstruct
public void registerListeners() {
log.debug("Registering Spring managed HibernateEventListeners");
EventListenerRegistry listenerRegistry = ((SessionFactoryImpl) entityManagerFactory
.getSessionFactory()).getServiceRegistry().getService(
EventListenerRegistry.class);
List<HibernateEventListener> eventListeners = hibernateSpringIntegratorRegistry
.getHibernateEventListeners();
for (HibernateEventListener hel : eventListeners) {
log.debug("Registering: {}", hel.getClass());
if (PreInsertEventListener.class.isAssignableFrom(hel.getClass())) {
listenerRegistry.appendListeners(EventType.PRE_INSERT,
(PreInsertEventListener) hel);
}
if (PreUpdateEventListener.class.isAssignableFrom(hel.getClass())) {
listenerRegistry.appendListeners(EventType.PRE_UPDATE,
(PreUpdateEventListener) hel);
}
if (PreDeleteEventListener.class.isAssignableFrom(hel.getClass())) {
listenerRegistry.appendListeners(EventType.PRE_DELETE,
(PreDeleteEventListener) hel);
}
if (PostInsertEventListener.class.isAssignableFrom(hel.getClass())) {
listenerRegistry.appendListeners(EventType.POST_INSERT,
(PostInsertEventListener) hel);
}
if (PostUpdateEventListener.class.isAssignableFrom(hel.getClass())) {
listenerRegistry.appendListeners(EventType.POST_UPDATE,
(PostUpdateEventListener) hel);
}
if (PostDeleteEventListener.class.isAssignableFrom(hel.getClass())) {
listenerRegistry.appendListeners(EventType.POST_DELETE,
(PostDeleteEventListener) hel);
}
// Currently we do not need other types of eventListeners. Else this method needs to be extended.
}
}
}
The "Registry":
#Component
public class HibernateSpringIntegratorRegistry {
#Autowired(required = false)
private List<HibernateEventListener> hibernateEventListeners;
public List<HibernateEventListener> getHibernateEventListeners() {
if (hibernateEventListeners == null) {
return Collections.emptyList();
}
return hibernateEventListeners;
}
}
And here's an example implementation:
#Component
public class MailGenerationEventListener implements HibernateEventListener,
PostDeleteEventListener, PostInsertEventListener, PostUpdateEventListener {
#Override
public void onPostDelete(PostDeleteEvent event) {
Class<?> entityClass = event.getEntity().getClass();
...
}
#Override
public void onPostInsert(PostInsertEvent event) {
Class<?> entityClass = event.getEntity().getClass();
...
}
#Override
public void onPostUpdate(PostUpdateEvent event) {
Class<?> entityClass = event.getEntity().getClass();
...
}
}
During an upgrade from hibernate 3.6 to 4.2, we needed to have a custom validator that uses spring-managed beans by doing the following configuration:
<!-- Make our validators use DI if necessary -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- other props -->
<property name="hibernateProperties">
<map>
<entry key="javax.persistence.validation.factory" value-ref="validator" />
</map>
</property>
</bean>
I am using Spring 3.0 for my project, I am having a class MySingletonClass, it is singleton as below :
//#Component("mySingletonClass")
public class MySingletonClass {
private static MySingletonClass obj = new MySingletonClass();
public static MySingletonClass getSingleObj() {
return obj;
}
}
spring xml bean configuration for this class is as below :
<bean id="mySingletonClass" class="app.MySingletonClass" factory-method="getSingleObj" />
I was trying to remove bean configuration and use annotation. how do I write annotation for factory method?
Thanks in advance !!
Spring creates instances like singleton by default. You can just do.
#Component("mySingletonClass")
public class MySingletonClass {
}
And if you don't change scope your component is singleton.
Spring component's are automatically created as Singletons.
Declare the annotation #Controller on the class
#Controller
public class MySingletonClass {
}
Then in your Spring Config file, declare like:
<bean id="mySingleton" class="com.package.MySingletonClass">
Then to use in another class you can use Autowiring or Setter/Constructor dependency injection.
#Component
public class OtherClass {
#Autowired
private MySingletonClass mySingleton;
}