I am working on this Spring MVC project where I have trouble getting this Dao class auto wired in the controller through an Interface that is implemented by the Dao. This is portion of my spring-config.xml. I am using aspectJ, Annotation and TX management.
<aop:aspectj-autoproxy />
<context:component-scan base-package="com.simulator" />
<context:annotation-config />
<tx:annotation-driven />
<context:property-placeholder
location="classpath*:config.properties" />
<bean id="oidDao" class="com.simulator.service.OidDao">
<property name="ipaddressNC" value="${ipaddressNC}" />
<property name="ipaddressOM" value="${ipaddressOM}" />
</bean>
Dao class:
#Component
public class OidDao implements OidManager {
#Autowired
private SessionFactory sessionFactory;
private String ipaddressNC;
private String ipaddressOM;
public String getIpaddressNC() {
return this.ipaddressNC;
}
public void setIpaddressNC(String ipaddressNC) {
this.ipaddressNC = ipaddressNC;
}
public String getIpaddressOM() {
return ipaddressOM;
}
public void setIpaddressOM(String ipaddressOM) {
this.ipaddressOM = ipaddressOM;
}
OidManager:
public interface OidManager {
public String getIpaddressNC();
public String getIpaddressOM();
}
Controller:
#Controller
public class HomeController {
#Autowired
OidManager oim;
#RequestMapping(value = "/", method = RequestMethod.GET)
public String indexpage(ModelMap modelMap) {
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"spring-config.xml"});
o = (OidManager)context.getBean("oidDao");
o.getIpaddressNC(); // ---> this returns data read from ext properties file and works fine
oim.getIpaddressNC(); // ---> this returns null`
I am trying to re-use the Dao, hence I dont want to call the ApplicationContext multiple times from each method. What am I doing wrong? If I make the variables getIpaddressNC, getIpaddressOM static, then auto wiring works, if not oim returns null though the variables are initialized via setters on application load.
You used both Component Scanning and Manual Wiring for OidDao. You defined oidDao in xml config, as follows:
<bean id="oidDao" class="com.simulator.service.OidDao">
<property name="ipaddressNC" value="${ipaddressNC}" />
<property name="ipaddressOM" value="${ipaddressOM}" />
</bean>
Then, added a Component annotation on OidDao, as follows:
#Component
public class OidDao implements OidManager {
...
}
Drop the Component annotation and you'll be fine, i guess! Because otherwise, <context:component-scan base-package="com.simulator" /> will pick OidDao and instantiate an instance from it with default constructor and without calling your setters.
You are using #Component annotation + you have also defined a bean. Therefore actually two beans are created. One created due to use of #Component would have the properties set to 'null'. This is expected since you are not setting the properties to any value. Either remove #Component annotation and use 'autowire-candidate="true"' property on bean definition or else remove the bean definition in XML and use relevant annotation on the class to set properties to correct values from property file.
Change your bean definition to:
<bean id="oim" class="com.simulator.service.OidDao">
<property name="ipaddressNC" value="${ipaddressNC}" />
<property name="ipaddressOM" value="${ipaddressOM}" />
</bean>
Let this create bean with id oim which can be set to the property oim in your Controller.
Related
so I'm trying to run a sql query within this java app. I think I have the DAO set up correctly but it can't find the XML file which contains my queries. The code in question for my DAO implementation is:
private Properties queries;
public void setQueries(Properties queries) {
this.queries = queries;
}
public Boolean checkAssigned(String Id) {
String sql = queries.getProperty("CHECK_IF_ASSIGNED");
Map<String,Object> params = new HashMap<>();
List<String> assignedList;
params.put(":Id",Id);
LOG.info("Checking to see if already assigned \n" + "sql=" + sql
+ "\n" + "params=" + params);
assignedList = getNamedParameterJdbcTemplate().query(sql,params,
new assignedMapper());
if (assignedList == null || assignedList.size() == 0) {
ScreenVo.setSwitch(false);
}
else {
ScreenVo.setSwitch(true);
}
return ScreenVo.getSwitch();
}
My DAO is just:
public interface ScreenDao {
Boolean checkAssigned(String Id);
}
My queries.xml file looks like:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<util:properties id="queries">
<prop key="CHECK_IF_ASSIGNED">
<![CDATA[
--Long query
]]>
</prop>
</util:properties>
</beans>
The bean for the dao in the applicationContext.xml is:
<bean id="screenDaoImpl" class="com.corp.apps.actionator.dao.ScreenDaoImpl">
<property name="dataSource" ref="datasource"/>
<property name="queries" ref="queries"/>
</bean>
And my declaration of the queries file in the applicationContext is:
<import resource="classpath:queries.xml"/>
It's declared in my web.xml in a similar fashion.
I tried to include everything that could possibly be relevant. I've tried autowiring the bean in ScreenDaoImpl.java but that didn't work. I'm really not sure where to go from here, or what I might have done wrong.
EDIT:
The exception I'm getting is:
javax.faces.event.MethodExpressionActionListener.processAction java.lang.NullPointerException
And my screenDaoImpl is declared before use as:
private static ScreenDao screenDao = new ScreenDaoImpl();
Spring-Bean screenDaoImpl must be created through Spring context, in this case Spring can inject required properties (dataSource and queries) in created bean.
I don't know your architecture of application. But I can offer you a couple of ways.
1 - If you want use screenDaoImpl in spring-bean which declared in spring-xml then you can do it like this:
<bean id="screenServiceImpl" class="com.corp.apps.actionator.service.ScreenServiceImpl">
<property name="screenDao" ref="screenDaoImpl"/>
</bean>
The better way is make all your application in Spring. And create (and inject) beans by spring-context xml. Do not create bean-objects by new. Spring can not inject properties in these objects.
If it is difficult then try to find examples of applications on the Spring site. Maybe try spring-boot (without xml).
2 - If you want use screenDaoImpl in non-spring object you can get screenDaoImpl from spring-context by "bridge". Create class:
package com.corp.apps.actionator.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class AppSpringBridge implements ApplicationContextAware {
private static ApplicationContext context;
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
}
public static ApplicationContext getApplicationContext() {
return context;
}
}
Define bean in application-context.xml:
<bean id="springBridge" class="com.corp.apps.actionator.util.AppSpringBridge />
Spring create this bean, but method getApplicationContext() (and context property) of this bean is static. And we can use getApplicationContext() in any methods:
ScreenDao screenDao = (ScreenDao)AppSpringBridge.getApplicationContext().getBean("screenDaoImpl");
I fixed it, and for posterity's sake I'll post my solution here:
First I autowired my screenDao bean in the invoking class, and then I created a static method to set screenDao.
#Autowired
private static ScreenDao screenDao;
#PostConstruct
public static void setScreenDao(ScreenDao newScreenDao) {
screenDao = newScreenDao;
}
#PostConstruct
public ScreenDao getScreenDao() {
return screenDao;
}
I'm not really sure if getScreenDao does anything but I added it as well.
Then in my application context I created a bean I called initialize to invoke the static method.
<bean id="initialize" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="com.corp.apps.consolidator.backing.ScreenBean"/>
<property name="targetMethod" value="setScreenDao"/>
<property name="arguments">
<list>
<ref bean="screenDao"/>
</list>
</property>
</bean>
These two changes resolved my issue.
This may looks like a duplicate of this question. But this is different.
I was trying to refactor my legacy code by using method injection in spring.
I have a bean class which contains many static helper methods. My targeted method as follows:
Context.java
private static MessageSender messageSender;
//...
public static MessageSender getMessageSender(){
return messageSender;
}
Context bean
<bean id="context" class="org.abc.Context">
<property name="messageSender"><ref bean="mailMessageSender"/></property>
</bean>
MailMessageSender.java
public abstract class MailMessageSender{
protected abstract Session createSession();
//using createSession() somewhere in this class
}
MailMessageSender bean
<bean id="session" class="javax.mail.Session" scope="prototype" />
<bean id="mailMessageSender" class="org.abc.MailMessageSender">
<lookup-method name="createSession" bean="session"/>
</bean>
I'm getting invalid property error when I'm installing the project.
You can't inject static field, change your variable in Context.java become like this:
private MessageSender messageSender;
//...
public MessageSender getMessageSender(){
return messageSender;
}
A prototypical portion of an application context:
<bean id="option_A" class="class_a" lazy-init="true"/>
<bean id="option_B" class="class_b" lazy-init="true" depends-on="setup_bean"/>
<alias name="option_${OPTION_PROPERTY}" alias="thingChosen"/>
<bean id="setup_bean" class="class_setup" lazy-init="true"/>
The concept here is that if OPTION_PROPERTY is set to "A", then
<bean id="foo" class="whatever"><property name="bar" ref="thingChosen"/></bean>
will get an instance of class_a injected into the bar property, and if the property is set to "B", then it will get an instance of class b injected, but class b has a hidden dependency on setup_bean (which class a lacks), so setup_bean must be created first.
What is happening is that if OPTION_PROPERTY is set to "A", then setup_bean is still created. I've tried this using Spring 3.2.4.RELEASE, and it's consistent. This seems like either a bug or a misunderstanding on my part.
If a bean is lazy-init, then shouldn't depends-on beans wait until that bean is lazily created before being created themselves?
If a bean is lazy-init, then shouldn't depends-on beans wait until
that bean is lazily created before being created themselves?
Yes. In other words option_B will not be created until setup_bean is requested and initialized. If option_B is requested first, then that will force setup_bean to be initialized first.
The documentation says
However, when a lazy-initialized bean is a dependency of a singleton
bean that is not lazy-initialized, the ApplicationContext creates the
lazy-initialized bean at startup, because it must satisfy the
singleton's dependencies.
Therefore, this bean declaration
<bean id="foo" class="whatever"><property name="bar" ref="thingChosen"/></bean>
will force the initialization of thingChosen, which in this case is aliasing option_A.
I cannot reproduce what you are experiencing (and should not). Double check what you are doing. Maybe another bean is referencing setup_bean.
Here's an SSCCE
public class Test {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
System.out.println("context initialized");
context.getBean("shouldnot");
}
public static class MyClass {
public MyClass() {
System.out.println("myclass");
}
}
public static class SetupBean {
public SetupBean() {
System.out.println("setup");
}
}
public static class MyOtherClass {
private MyClass myClass;
public MyOtherClass() {
System.out.println("myotherclass");
}
public MyClass getMyClass() {
return myClass;
}
public void setMyClass(MyClass myClass) {
this.myClass = myClass;
}
}
}
and spring.xml beans
<bean id="myref" class="test.Test$MyClass" lazy-init="true"></bean>
<bean id="shouldnot" class="test.Test$MyClass" lazy-init="true" depends-on="setup_bean"></bean>
<bean class="test.Test$MyOtherClass" >
<property name="myClass" ref="myref"></property>
</bean>
<bean id="setup_bean" class="test.Test$SetupBean" lazy-init="true"></bean>
it prints (minus Spring logs)
myotherclass
myclass
context initialized
setup
myclass
In other words, setup is only created when shouldnot is requested.
It turns out that elsewhere in the context, there's this little gem:
<context:annotation-config />
This, it appears, results in lazy-init being ignored.
Trying to figure out how the exclusion machinery works is the next step, but is out-of-scope for this question.
How would I specify an anonymous inner bean in a named Spring Service?
#Service("myNamedService")
public class myNamedServiceClass {
private InnerBeanType innerBean;
#Autowired
public void setInnerBean(InnerBeanType innerBean) {
this.innerBean = innerBean;
}
}
I'm basically trying to achieve the equivalent of the following Spring XML wiring:
<bean name="myNamedService" class="somePackage.myNamedServiceClass">
<property name="innerBean">
<bean class="somePackage.InnerBeanType"/>
</property>
</bean>
Equivalent using pure annotations is I think not possible. You can use #Configuration though if the purpose is to not expose innerBean as a visible bean this way:
#Bean
public MyNamedServiceBean myNamedServiceBean(){
MyNamedServiceClass myNamedServiceBean = new MyNamedServiceClass();
myNamedServiceBean.setInnerBean(new InnerBeanType());
return myNamedServiceBean;
}
I have the following abstract class, with a property called portletBaseViewName which is meant to be different for every concrete Controller extending AbstractController.
public abstract class AbstractController {
private String portletBaseViewName;
protected String getPortletBaseViewName() {
return portletBaseViewName;
}
#Required
#Value("")
public void setPortletBaseViewName(String portletBaseViewName) {
this.portletBaseViewName = portletBaseViewName;
}
}
#Controller
#RequestMapping("VIEW")
public class ReservationOfBooksViewController extends AbstractController{}
I know that is possible declaring the injections in a XML, doing so:
<bean id="abstractController" class="es.alcampo.portalweb.portlets.common.controller.AbstractController" abstract="true">
<property name="portletBaseViewName" value="" />
</bean>
<bean id="reservationOfBooksViewController" class="es.example.portalweb.portlets.reservationofbooks.controller.ReservationOfBooksViewController" parent="abstractController">
<property name="portletBaseViewName" value="reservationOfBooks" />
</bean>
<bean id="myShopViewController" class="es.example.portalweb.portlets.reservationofbooks.controller.MyShopViewController" parent="abstractController">
<property name="portletBaseViewName" value="myShop" />
</bean>
Do I need to redefine?:
#Controller
#RequestMapping("VIEW")
public class ReservationOfBooksViewController extends AbstractController{
#Value("reservationOfBooks")
public void setPortletBaseViewName(String portletBaseViewName) {
super.setPortletBaseViewName(portletBaseViewName);
}
}
I don't like the previous option, which would be the most elegant option if there is to reach the purpose of injecting one value or another depending on the concrete class through annotations?
I know inheritance and annotations sometimes conflict.
Thanks a lot.
Do you actually need #Value here?
#Value is useful when it contains some expressions evaluated by Spring at runtime. Otherwise you can replace it with explicit initialization (and keeping the setter method allows you to override this values from XML configuration):
public abstract class AbstractController {
protected String portletBaseViewName = "";
public void setPortletBaseViewName(String portletBaseViewName) {
this.portletBaseViewName = portletBaseViewName;
}
}
#Controller
#RequestMapping("VIEW")
public class ReservationOfBooksViewController extends AbstractController{
public ReservationOfBooksViewController() {
this.portletBaseViewName = "reservationOfBooks";
}
}
As shown by #axtavt in previous answer, you don't need any annotation in AbstractController. In addition, you don't need to define abstractController in XML. In case, you want to configure common properties in all of its subclasses, you can put them in abstract bean (without any class name):
<!-- define common properties in abstract bean-->
<bean id="controllerTemplate" abstract="true" />
<bean id="reservationOfBooksViewController" class="es.example.portalweb.portlets.reservationofbooks.controller.ReservationOfBooksViewController" parent="controllerTemplate">
<property name="portletBaseViewName" value="reservationOfBooks" />
In subclasses, #Value annotation is not required and you can use 'getPortletBaseViewName()' method to get view name.