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.
Related
Trying to autowire Spring bean with property, but still getting NPE. Snippets:
INFO: Loading XML bean definitions from class path resource [autoWireByName.xml]
Exception in thread "main" today do push-ups for 30 mins
java.lang.NullPointerException
at com.springAutoWireByName.KabadiCoach.getFortune(KabadiCoach.java:23)
at com.springAutoWireByName.AutoWireByName.main(AutoWireByName.java:13)
KabadiCoach.java
package com.springAutoWireByName;
public class KabadiCoach {
private SadFortune sadFortune;
/*public KabadiCoach(){
System.out.println("inside default Constructor");
}*/
public String getDailyWorkout()
{
return "today do push-ups for 30 mins";
}
public void setSadFortune(SadFortune fortune) {
sadFortune = fortune;
}
public String getFortune() {
return sadFortune.getSadFortune();
}
}
SadFortune.java
package com.springAutoWireByName;
public class SadFortune {
public String getSadFortune()
{
System.out.println();
return "your day wont be good enough Sorry!!!";
}
}
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- bean definitions here -->
<bean name="Fortune" class="com.springAutoWireByName.SadFortune">
</bean>
<bean id="myCoach" class="com.springAutoWireByName.KabadiCoach" autowire="byName" />
<!-- this is just a prototype to define actual just make use of this file-->
</beans>
main
package com.springAutoWireByName;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AutoWireByName {
public static void main(String[] args) {
ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("autoWireByName.xml");
KabadiCoach co = context.getBean("myCoach",KabadiCoach.class);
System.out.println(co.getDailyWorkout());
System.out.println(co.getFortune());
}
}
after running the above code I am getting the error message as listed and when I change the method to static
public static String getSadFortune()
{
System.out.println();
return "your day wont be good enough Sorry!!!";
}
In class 2 I got the desired output. Why?
Basically the SadFortune member is still null, which is why it works if the getSadFortune() method will be made static.
Until now you only tell Spring to instantiate a Fortune bean and a KabadiCoach, but you have to tell Spring that some members in the KabadiCoach need to be autowired too.
Try this in your Spring configuration file:
<bean id="fortune" class="com.springAutoWireByName.SadFortune"></bean>
<bean id="myCoach" class="com.springAutoWireByName.KabadiCoach" autowire="byName">
<property name="fortune" ref="fortune" />
</bean>
EDIT: Sorry, overread the autowire="byName" attribute. In this case you probably just have write the name in lower case.
<bean id="fortune" class="com.springAutoWireByName.SadFortune"/>
<bean id="myCoach" class="com.springAutoWireByName.KabadiCoach" autowire="byName"/>
I have a small Java application which connects to a MySQL database. For database connectivity ONLY, I'd like to use Spring to manage a JNDI based connection pool.
I have a working implementation for the above but this requires manually loading the JNDI connection bean, whereas I'd like to use #Autowired.
How can I convert my working code to one that uses #Autowired to get the JNDI connection ?
This is my beans.xml file (inside src/main/resources folder):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns= ....>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/Database"/>
</bean>
<bean id="databaseMapper2Impl"
class="com.dataaccess.DatabaseMapper2Impl">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
The is a section of my DatabaseMapper2Impl class:
public class DatabaseMapper2Impl {
private DataSource dataSource;
private JdbcTemplate jdbcTemplateObject;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
this.jdbcTemplateObject = new JdbcTemplate(dataSource);
}
public OrderDTO getOrder(String orderNumber, String envToUse) {
String getOrderSql = "SELECT * FROM REPORTING.ORDER where ORDER_NUMBER = ? limit 1";
List<OrderDTO> orders = jdbcTemplateObject.query(getOrderSql, new Object[] { orderNumber }, new OrderMapper());
if (orders == null || orders.isEmpty()) {
return null;
} else {
return orders.get(0);
}
}
}
This is the class where the JNDI connection bean is manually instantiated:
public class DataDelegateImpl {
public OrderDTO getOrder(String orderNumber, String envToUse) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
DatabaseMapper2Impl x = (DatabaseMapper2Impl) context.getBean("databaseMapper2Impl");
return x.getOrder(orderNumber, envToUse);
}
}
In order for Spring to manage the instantiation and injection of your DatabaseMapper2Implbean, you will have to create an ApplicationContext, and declare the bean in that context, exactly as you have done.
If the question is just how to avoid using XML for that declaration, you could annotate DatabaseMapper2Impl with #Component and instead use
ApplicationContext context = new AnnotationConfigApplicationContext(DatabaseMapper2Impl.class);
to create the context.
If you really need to have the DatabaseMapper2Impl #Autowired into an instance of DataDelegateImpl, then that instance would also have to be controlled by Spring, so you'd have to create the context at a higher level and make the DataDelegateImpl a bean as well.
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.
I know this may looks like a previously asked question but I'm facing a different problem here.
I have a utility class that has only static methods. I don't and I won't take an instance from it.
public class Utils{
private static Properties dataBaseAttr;
public static void methodA(){
}
public static void methodB(){
}
}
Now I need Spring to fill dataBaseAttr with database attributes Properties.Spring config is:
<?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-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<util:properties id="dataBaseAttr"
location="file:#{classPathVariable.path}/dataBaseAttr.properties" />
</beans>
I already done it in other beans but the problem here in this class (Utils) isn't a bean, And if I make it a bean nothing changes I still can't use the variable since the class will not be instantiated and variable always equals null.
You have two possibilities:
non-static setter for static property/field;
using org.springframework.beans.factory.config.MethodInvokingFactoryBean to invoke a static setter.
In the first option you have a bean with a regular setter but instead setting an instance property you set the static property/field.
public void setTheProperty(Object value) {
foo.bar.Class.STATIC_VALUE = value;
}
but in order to do this you need to have an instance of a bean that will expose this setter (its more like an workaround).
In the second case it would be done as follows:
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="foo.bar.Class.setTheProperty"/>
<property name="arguments">
<list>
<ref bean="theProperty"/>
</list>
</property>
</bean>
On you case you will add a new setter on the Utils class:
public static setDataBaseAttr(Properties p)
and in your context you will configure it with the approach exemplified above, more or less like:
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="foo.bar.Utils.setDataBaseAttr"/>
<property name="arguments">
<list>
<ref bean="dataBaseAttr"/>
</list>
</property>
</bean>
I've had a similar requirement: I needed to inject a Spring-managed repository bean into my Person entity class ("entity" as in "something with an identity", for example an JPA entity). A Person instance has friends, and for this Person instance to return its friends, it shall delegate to its repository and query for friends there.
#Entity
public class Person {
private static PersonRepository personRepository;
#Id
#GeneratedValue
private long id;
public static void setPersonRepository(PersonRepository personRepository){
this.personRepository = personRepository;
}
public Set<Person> getFriends(){
return personRepository.getFriends(id);
}
...
}
.
#Repository
public class PersonRepository {
public Person get Person(long id) {
// do database-related stuff
}
public Set<Person> getFriends(long id) {
// do database-related stuff
}
...
}
So how did I inject that PersonRepository singleton into the static field of the Person class?
I created a #Configuration, which gets picked up at Spring ApplicationContext construction time. This #Configuration gets injected with all those beans that I need to inject as static fields into other classes. Then with a #PostConstruct annotation, I catch a hook to do all static field injection logic.
#Configuration
public class StaticFieldInjectionConfiguration {
#Inject
private PersonRepository personRepository;
#PostConstruct
private void init() {
Person.setPersonRepository(personRepository);
}
}
As these answers are old, I found this alternative. It is very clean and works with just java annotations:
To fix it, create a “none static setter” to assign the injected value for the static variable. For example :
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component
public class GlobalValue {
public static String DATABASE;
#Value("${mongodb.db}")
public void setDatabase(String db) {
DATABASE = db;
}
}
https://www.mkyong.com/spring/spring-inject-a-value-into-static-variables/
I have such singleton class:
package ua.org.bytes.ewt;
import org.apache.struts2.ServletActionContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import ua.org.bytes.ewt.dao.CategoriesManager;
import ua.org.bytes.ewt.dao.ShortcutsManager;
/**
*
* #author Vitaliy Ganzha
*/
public class ApplicationSupervisor {
private static final ApplicationSupervisor INSTANCE = new ApplicationSupervisor();
private CategoriesManager categoriesManager;
public void setCategoriesManager(CategoriesManager categoriesManager) {
this.categoriesManager = categoriesManager;
}
public void setShortcutsManager(ShortcutsManager shortcutsManager) {
this.shortcutsManager = shortcutsManager;
}
private ShortcutsManager shortcutsManager;
public ShortcutsManager getShortcutsManager() {
return shortcutsManager;
}
private ApplicationSupervisor(){
/*WebApplicationContext context =
WebApplicationContextUtils.getRequiredWebApplicationContext(
ServletActionContext.getServletContext()
);
categoriesManager = (CategoriesManager)context.getBean("categoriesManager");
shortcutsManager = (ShortcutsManager)context.getBean("categoriesManager");*/
}
public static ApplicationSupervisor getInstance(){
return INSTANCE;
}
/**
* #return the categoriesManager
*/
public CategoriesManager getCategoriesManager() {
return categoriesManager;
}
}
And applicationContext.xml:
<beans default-autowire="autodetect">
<bean id="categoriesManager" class="ua.org.bytes.ewt.dao.CategoriesManagerImpl"></bean>
<bean id="shortcutsManager" class="ua.org.bytes.ewt.dao.ShortcutsManagerImpl"></bean>
<bean id="applicationSupervisor" class="ua.org.bytes.ewt.ApplicationSupervisor" singleton="true">
<property name="categoriesManager">
<ref local="categoriesManager"/>
</property>
<property name="shortcutsManager">
<ref local="shortcutsManager"/>
</property>
</bean>
</beans>
So, I had one class with all entity managers. All implementations on interfases CategoriesManager and ShortcutsManager I want to set with Spring IoC.
I've added listener into web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
But when I try to work with them, I get NullPointerException:
ApplicationSupervisor.getInstance().getShortcutsManager(); = will return null.
Please, help me, I'm new in Spring IoC.
Thank you!
It's not working because you have two singletons, not one. The first singleton is managed by ApplicationSupervisor.getInstance(), the second is managed by Spring. You haven't told Spring about the getInstance() factory method.
You need to declare your Spring bean to use getInstance():
<bean id="applicationSupervisor" class="ua.org.bytes.ewt.ApplicationSupervisor"
factory-method="getInstance">
<property name="categoriesManager">
<ref local="categoriesManager"/>
</property>
<property name="shortcutsManager">
<ref local="shortcutsManager"/>
</property>
</bean>
Note that singleton="true" is redundant here - all Spring beans are singletons by default.
With this configuration, you can access the singleton either through Spring's BeanFactory, bean injection, or programmatically via ApplicationSupervisor.getInstance().
However, this is not really a nice way to go about managing your singetons. Rather than having a static getInstance(), you should be injecting the ApplicationSupervisor into the beans that use it. This is the whole point of IoC.
Have you tried something like this to load your Application supervisor?
Spring doesn't hook into the java 'new' keyword
static {
INSTANCE = (ApplicationSupervisor)
new ClassPathXmlApplicationContext("/ApplicationContext.xml").getBean("applicationSupervisor");
}