I have a prototype spring application to play with spring-security and LDAP. The application works with the internal LDAP-Server. But when I want to define an individual connection with a xml-config it doesn't work. More specific: The LdapTemplate which should be instantiated by the xml-config stays a null-object. Here is the code:
public class UserRepo {
#Autowired
private LdapTemplate ldapTemplate; //stays null
public static final String BASE_DN = "dc=springframework,dc=org";
//this works, but is not desired:
public UserRepo() {
// final GenericXmlApplicationContext appContext = new GenericXmlApplicationContext("classpath:ldap.xml");
// appContext.refresh();
// ldapTemplate = (LdapTemplate)appContext.getBean(LdapTemplate.class);
// LdapContextSource lcs = new LdapContextSource();
// lcs.setUrl("ldap://127.0.0.1:389/");
// lcs.setUserDn(BASE_DN);
// lcs.setDirObjectFactory(DefaultDirObjectFactory.class);
// lcs.setAnonymousReadOnly(true);
// lcs.afterPropertiesSet();
// ldapTemplate = new LdapTemplate(lcs);
}
My config looks like this:
<?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:ldap="http://www.springframework.org/schema/ldap"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/ldap http://www.springframework.org/schema/ldap/spring-ldap.xsd">
<ldap:context-source
id="contextSource"
url="ldap://localhost:389"
base="dc=example,dc=com"
username="cn=Manager"
password="secret" />
<ldap:ldap-template id="ldapTemplate" />
<bean id="userRepo" class="user.UserRepo">
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>
</beans>
I have put the ldap.xml one time in the src-dir and another time in the ressource-dir, both didn't work.
I hope you can tell me what I'm doing wrong.
Add a #Component annotation to your UserRepo class and a proper annotation-config (or component-scan element if required). Since your commented-out code works, the LdapTemplate bean is created succesfully, and injected because you use a GenericXmlApplicationContext. To test it with annotations you need an AnnotationConfigApplicationContext instead.
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.
I have some programmatically created beans that I am initializing via AutowireCapableBeanFactory.autowireBean() as shown below:
spring.xml:
<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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:annotation-config/>
<bean id="MyService" class="...">
<property name="someProp" value="primitiveValue"/>
</bean>
<bean id="MyBean" class="...">
<property name="someString" value="primitiveValue"/>
</bean>
</beans>
MyBean.java
public class MyBean implements InitializingBean {
#Autowired MyService myService;
private String someString;
public void setSomeString (String someString) {
this.someString = someString;
}
public void afterPropertiesSet () {}
}
Caller:
MyBean bean = new MyBean(arg1, arg2, arg3);
autowireCapableBeanFactory.autowireBean(bean);
This correctly autowires bean.myService as expected. However it does not populate primitive properties like bean.someString.
Looking at the docs and this answer, I though something like this would work:
MyBean bean = new MyBean(arg1, arg2, arg3);
autowireCapableBeanFactory.autowireBean(bean);
autowireCapableBeanFactory.initializeBean(bean, "name");
But alas, someString is still null. I have found lots of references stating what will not work to initialize class properties, but nothing showing what will work.
Any ideas?
Found I could use AutowireCapableBeanFactory.applyBeanPropertyValues() to accomplish what I wanted. Code to inject both #Autowired beans and primitive properties looks like this:
#Autowired AutowireCapableBeanFactory beanFactory;
...
MyBean bean = new MyBean();
beanFactory.autowireBean(bean);
beanFactory.applyBeanPropertyValues(bean, bean.getClass().getSimpleName());
My application uses struts and spring frameworks. I have a class FormA which has an autowired property in it. When I try to instantiate it while writing unit tests I get a Null Pointer Exception. Here is my code.
My ClassA:
public class FormA{
private String propertyOne;
#Autowired
private ServiceClass service;
public FormA(){
}
}
My unit test method:
#Test
public void testFormA(){
FormA classObj = new FormA();
}
#Autowired only works when object life cycle is managed by Spring.
You'll need to run your tests with #RunWith(SpringJUnit4ClassRunner.class), and instead of instantiating FormA manually, inject it in the test class as well, using #Autowired.
When you create an object by new, autowire\inject don't work...
as workaround you can try this:
create your template bean of NotesPanel
<bean id="notesPanel" class="..." scope="prototype">
<!-- collaborators and configuration for this bean go here -->
</bean>
and create an istance in this way
applicationContext.getBean("notesPanel");
PROTOTYPE : This scopes a single bean definition to have any number of object instances.
anyway a unit test should be
Test class
#RunWith( SpringJUnit4ClassRunner.class )
#ContextConfiguration(locations = { "classpath:META-INF/your-spring-context.xml" })
public class UserServiceTest extends AbstractJUnit4SpringContextTests {
#Autowired
private UserService userService;
#Test
public void testName() throws Exception {
List<UserEntity> userEntities = userService.getAllUsers();
Assert.assertNotNull(userEntities);
}
}
your-spring-context.xml
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="userService" class="java.package.UserServiceImpl"/>
</beans>
I am learning JdbcTemplate with Spring and when i am running my java application i am getting null pointer on this line:
return jdbcTemplate.queryForMap(sql, id);
Please find the whole class below:
public class CustomerDaoImpl implements CustomerDAO{
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource ds) {
dataSource = ds;
}
public Map getCustomerById(String id) {
String sql = "SELECT * FROM CUSTOMER WHERE CUST_ID = ?";
return jdbcTemplate.queryForMap(sql, id);
}
Please find my SpringContext file below:
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Scans within the base package of the application for #Components to
configure as beans -->
<context:property-placeholder location="classpath:db.properties" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<bean id="customerDAO" class="com.tuto.dao.impl.CustomerDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
Please find my Main method below:
public class JdbcTemplateApp {
public static void main(String[] args) {
// if you have time,
// it's better to create an unit test rather than testing like this :)
ApplicationContext context = new ClassPathXmlApplicationContext(
"integration.xml");
CustomerDAO customerDAO = (CustomerDAO) context.getBean("customerDAO");
Map customerA = customerDAO.getCustomerById("1");
System.out.println("Customer A : " + customerA);
}
}
Please find below my exception in eclipse console:
INFO: Loaded JDBC driver: oracle.jdbc.driver.OracleDriver
Exception in thread "main" java.lang.NullPointerException
at com.tuto.dao.impl.CustomerDaoImpl.getCustomerById(CustomerDaoImpl.java:23)
at com.tuto.main.JdbcTemplateApp.main(JdbcTemplateApp.java:23)
Any idea why it is null please?
Thanks in advance for any help
Change setDataSource to:
public void setDataSource(DataSource ds) {
jdbcTemplate = new JdbcTemplate(ds);
}
You can extend org.springframework.jdbc.core.support.JdbcDaoSupport in your DAOImpl Class and use inherited getJdbcTemplate() method to get the jdbcTemplate. in this case you can remove the variable jdbcTemplate from your class
You never initialize jdbcTemlpate instance variable. In this case it's initialized as null and you're getting NullPointerException (you can't call methods on null). You need to initialize jdbcTemplate by yourself.
To quote Java Language Specification:
Each class variable, instance variable, or array component is
initialized with a default value when it is created [...] For all
reference types the default value is null.
I'm trying to replicate something that works with XML config using annotated configuration classes. The problem I'm hitting is that property sources defined in the child context are not accessible.
The xml that works looks like
Parent context :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="proxyChannelQueue" class="java.util.concurrent.ArrayBlockingQueue">
<constructor-arg value="10"/>
</bean>
</beans>
Child Context :
<?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"
xmlns:p="http://www.springframework.org/schema/p"
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">
<context:property-placeholder location="proxy-host.properties"/>
<bean class="org.eclipse.jetty.server.Server"
p:handler-ref="proxyHostHandler"
init-method="start">
<constructor-arg value="${proxyHostPort}"/>
</bean>
<bean id="proxyHostHandler" class="com.sjl.web.ProxyHostHandler"
p:proxyChannelQueue-ref="proxyChannelQueue"/>
</beans>
Start up code :
ClassPathXmlApplicationContext parentContext = new ClassPathXmlApplicationContext("test/parent-context.xml");
ClassPathXmlApplicationContext childContext = new ClassPathXmlApplicationContext(new String[] {"test/child-context.xml"}, parentContext);
My attempt at doing this using configuration classes looks like.
Parent Context :
#Configuration
public class ParentConfiguration {
#Bean(name = "proxyChannelQueue")
public BlockingQueue<ProxyChannel> getProxyChannelQueue() {
return new ArrayBlockingQueue<ProxyChannel>(10);
}
}
Child Context :
#Configuration
#PropertySource("classpath:proxy-host.properties")
public class ChildContext {
private static final Logger LOGGER = LoggerFactory.getLogger(ChildContext.class);
#Autowired
private Environment environment;
#Resource(name = "proxyChannelQueue")
private BlockingQueue<ProxyChannel> proxyChannelQueue;
public static void main(String[] args) {
new HierarchicalAnnotationConfigApplicationContext(ChildContext.class);
}
#Bean
public Server getJettyServer() throws Exception {
int proxyHostPort = environment.getProperty("proxyHostPort", Integer.class);
Server server = new Server(proxyHostPort);
server.setHandler(getHandler());
server.start();
return server;
}
#Bean
public Handler getHandler() {
ProxyHostHandler proxyHostHandler = new ProxyHostHandler();
proxyHostHandler.setProxyChannelQueue(proxyChannelQueue);
return proxyHostHandler;
}
}
Start up code :
AnnotationConfigApplicationContext parentContext = new AnnotationConfigApplicationContext(ParentConfiguration.class);
AnnotationConfigApplicationContext childContext = new AnnotationConfigApplicationContext();
childContext.setParent(parentContext);
childContext.register(ChildContext.class);
childContext.refresh();
I'm getting a null pointer while trying to retrieve the proxyHostPort within the ChildContext getJettyServer method. Inspecting the environment variable shows that it contains only 2 property sources (systemProperties and systemEnvironment) and not the 3 I expect.
The same configuration works if I run them as a single combined context. E.g. :
AnnotationConfigApplicationContext parentContext = new AnnotationConfigApplicationContext(ParentConfiguration.class, ChildContext.class);
However I want the isolation that using parent contexts provide.
Cheers,
Peter