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());
Related
In my Spring Boot project when using the following validation rules in my DTO
#Length(max = 70)
#UnwrapValidatedValue
private Optional<String> vendorName;
I am getting the following exception
javax.validation.ValidationException: HV000182: No validation value unwrapper is registered for type java.util.Optional<java.lang.String>
I can't just find anywhere how to register custom validation value unwrapper in Spring
You should register a ValidatedValueUnwrapper to the validator.
The validator could be configured via the LocalValidatorFactoryBean:
<?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.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
<bean name="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="validationPropertyMap">
<util:map>
<entry key="hibernate.validator.validated_value_handlers"
value="com.mycompany.validator.OptionalValidatedValueUnwrapper"/>
</util:map>
</property>
</bean>
</beans>
or in java:
#Bean
public LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.getValidationPropertyMap().put("hibernate.validator.validated_value_handlers",
"com.mycompany.validator.OptionalValidatedValueUnwrapper");
return validator;
}
You could find a proper ValidatedValueUnwrapper implementation in the dropwizard framework (based on the Optional from guava).
public class OptionalValidatedValueUnwrapper extends ValidatedValueUnwrapper<Optional<?>> {
private final TypeResolver resolver = new TypeResolver();
#Override
public Object handleValidatedValue(final Optional<?> optional) {
return optional.orNull();
}
#Override
public Type getValidatedValueType(final Type type) {
ResolvedType resolvedType = resolver.resolve(type);
return resolvedType.typeParametersFor(Optional.class).get(0).getErasedType();
}
}
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.
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