#PostConstruct method is not called in Spring - spring

SampleBean:
package com.springexample;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class SampleBean {
private BeanTypeOne beanOne;
private BeanTypeTwo beanTwo;
public void init() {
System.out.println("This is from the init() method");
}
#PostConstruct
public void initAnnotation() {
System.out.println("This is from the initAnnotation() method");
}
and config file like this :
<bean id="SampleBean" class="com.springexample.SampleBean">
<property name="beanOne" ref="beanOneOne"></property>
<property name="beanTwo" ref="beanTwoOne"></property>
</bean>
And I don't have default-init-method attribute set on the beans tag.
Can any body tell why the #PostConstruct method does not get called.

You need <context:annotation-config/> (or <context:component-scan/>) to enable #PostConstruct handling.

Related

Load particular bean using Spring SPEL method

I have a requirement to load specific bean on a condition which i am reading from config properties .
I have two beans so i am trying to load it as below
public interface MediatorInt {
public void init();
}
class A implements MediatorInt {
init() { It does some task }
}
class B implements MediatorInt {
init(){ It does some task }
}
public class MasterNewGenImpl {
#Autowired
#Qualifier("config")
private Configuration config;
#Autowired
MediatorInt mediatorInt;
private final Logger logger = Logger.getLogger(getClass());
public void startService() {
mediatorInt.init();
}
}
<context:component-scan base-package="com.ca"/>
<bean id="config" class="com.ca.configuration.ConfigImplementation"/>
<bean id="masterSlave" class="com.ca.masterslave.A"/>
<bean id="systemState" class="com.ca.masterslave.B"/>
<bean id="masterSlaveNewGen" class="com.ca.masterslave.MasterNewGenImpl">
<property name = "mediatorInt" value="#{config.getMediatorMode() == 'true' ? 'systemState' : 'masterSlave'}" />
</bean>
But the bean is not getting loaded .
Can you please help if any error in the syntax or the method of using it .

Spring autowiring not working, getting `applicationDao` as null

Below are my classes and xml:
#Component
#Service("ApplicationService")
public class ApplicationServiceImpl implements ApplicationService{
public ApplicationDao getApplicationDao() {
return applicationDao;
}
public void setApplicationDao(ApplicationDao applicationDao) {
this.applicationDao = applicationDao;
}
#Autowired
private ApplicationDao applicationDao;
// some methods..
}
#Service
public interface ApplicationService {
// methods...
}
#Component
#Repository("ApplicationDao")
public class ApplicationDaoImpl implements ApplicationDao {
#Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
// other methods...
}
public interface ApplicationDao {
// methods...
}
xml file:
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven/>
<context:component-scan base-package="com" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- <property name="dataSource" ref="dataSource" /> -->
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
<bean id="ApplicationDao" class="com.dao.impl.ApplicationDaoImpl"/>
<bean id="ApplicationService" class="com.service.impl.ApplicationServiceImpl"/>
Here autowiring is not working.in ApplicationServiceImpl, I am getting applicationDao as null. Have not tested sessionFactory in ApplicationDaoImpl.
I know that if I am using #Component then bean declaration in xmnl is not required.
You should not instantiate service like that..
At the time of application loading, spring container will create all instances defined in spring.xml or annotated classes and it's dependencies..
So you have to access them with the following example code..
ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();
ApplicationService applicationService = (ApplicationService) applicationContext.getBean("ApplicationService");
Since ApplicationService is having property that is ApplicationServiceDAOImpl, it's already been created by spring container and will return you..
But in case of directly instantiating manually by you, you are just creating instance of ApplicationService but not for ApplicationServiceDAOImpl.. so it obviously returns null
I'm currently using this approach only to access beans or services..
update for comment
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext arg0)
throws BeansException {
applicationContext = arg0;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}
Hope it helps,
try a change like this:
import org.springframework.beans.factory.annotation.Qualifier;
#Autowired
#Qualifier("ApplicationDao")
private ApplicationDao applicationDao;
this give spring a hint.
If you are using annotations in your application, you should denote it using a tag :
<mvc:annotation-driven />
Add this line in application context xml above component scan tag.
Also, if you are using annotations, remove ApplicationDao and ApplicationService bean declarations from xml.
And don't mark you service and dao classes with both #Component and #Service or #Repository annotations. No need to mark them #Component there. Remove it.

ClasspathXmlApplicationContext with parent of the current ApplicationContext?

Due to another library's requirements, I must define an ApplicationContext in my main ApplicationContext with a name of default.context:
<?xml version="1.0"?>
<beans>
<bean name="default.context" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>../other-file.xml
</list>
</constructor-arg>
</bean>
<bean class="MyNiceDependency"/>
</beans>
How can I make MyNiceDependency available to the default.context context? I'm assuming I need to use the parent property of ClassPathXmlApplicationContext but how do I inject the current context to it?
Here's something that should get the job done:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class ThisApplicationContextFactoryBean implements FactoryBean<ApplicationContext>,
ApplicationContextAware {
private ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return this.applicationContext;
}
#Override
public ApplicationContext getObject() throws Exception {
return getApplicationContext();
}
#Override
public Class<?> getObjectType() {
return ApplicationContext.class;
}
#Override
public boolean isSingleton() {
return true;
}
}
Perhaps there's something better or, better yet, included with Spring?

How to read values from properties file?

I am using spring. I need to read values from properties file. This is internal properties file not the external properties file. Properties file can be as below.
some.properties ---file name. values are below.
abc = abc
def = dsd
ghi = weds
jil = sdd
I need to read those values from the properties file not in traditional way. How to achieve it? Is there any latest approach with spring 3.0?
Configure PropertyPlaceholder in your context:
<context:property-placeholder location="classpath*:my.properties"/>
Then you refer to the properties in your beans:
#Component
class MyClass {
#Value("${my.property.name}")
private String[] myValues;
}
To parse property with multiple comma-separated values:
my.property.name=aaa,bbb,ccc
If that doesn't work, you can define a bean with properties, inject and process it manually:
<bean id="myProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath*:my.properties</value>
</list>
</property>
</bean>
and the bean:
#Component
class MyClass {
#Resource(name="myProperties")
private Properties myProperties;
#PostConstruct
public void init() {
// do whatever you need with properties
}
}
There are various ways to achieve the same. Below are some commonly used ways in spring-
Using PropertyPlaceholderConfigurer
Using PropertySource
Using ResourceBundleMessageSource
Using PropertiesFactoryBean
and many more........................
Assuming ds.type is key in your property file.
Using PropertyPlaceholderConfigurer
Register PropertyPlaceholderConfigurer bean-
<context:property-placeholder location="classpath:path/filename.properties"/>
or
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:path/filename.properties" ></property>
</bean>
or
#Configuration
public class SampleConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
//set locations as well.
}
}
After registering PropertySourcesPlaceholderConfigurer, you can access the value-
#Value("${ds.type}")private String attr;
Using PropertySource
In the latest spring version you don't need to register PropertyPlaceHolderConfigurer with #PropertySource, I found a good link to understand version compatibility-
#PropertySource("classpath:path/filename.properties")
#Component
public class BeanTester {
#Autowired Environment environment;
public void execute() {
String attr = this.environment.getProperty("ds.type");
}
}
Using ResourceBundleMessageSource
Register Bean-
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:path/filename.properties</value>
</list>
</property>
</bean>
Access Value-
((ApplicationContext)context).getMessage("ds.type", null, null);
or
#Component
public class BeanTester {
#Autowired MessageSource messageSource;
public void execute() {
String attr = this.messageSource.getMessage("ds.type", null, null);
}
}
Using PropertiesFactoryBean
Register Bean-
<bean id="properties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:path/filename.properties</value>
</list>
</property>
</bean>
Wire Properties instance into your class-
#Component
public class BeanTester {
#Autowired Properties properties;
public void execute() {
String attr = properties.getProperty("ds.type");
}
}
In configuration class
#Configuration
#PropertySource("classpath:/com/myco/app.properties")
public class AppConfig {
#Autowired
Environment env;
#Bean
public TestBean testBean() {
TestBean testBean = new TestBean();
testBean.setName(env.getProperty("testbean.name"));
return testBean;
}
}
Here is an additional answer that was also great help for me to understand how it worked : http://www.javacodegeeks.com/2013/07/spring-bean-and-propertyplaceholderconfigurer.html
any BeanFactoryPostProcessor beans have to be declared with a static, modifier
#Configuration
#PropertySource("classpath:root/test.props")
public class SampleConfig {
#Value("${test.prop}")
private String attr;
#Bean
public SampleService sampleService() {
return new SampleService(attr);
}
#Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
If you need to manually read a properties file without using #Value.
Thanks for the well written page by Lokesh Gupta : Blog
package utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.io.File;
public class Utils {
private static final Logger LOGGER = LoggerFactory.getLogger(Utils.class.getName());
public static Properties fetchProperties(){
Properties properties = new Properties();
try {
File file = ResourceUtils.getFile("classpath:application.properties");
InputStream in = new FileInputStream(file);
properties.load(in);
} catch (IOException e) {
LOGGER.error(e.getMessage());
}
return properties;
}
}
Another way is using a ResourceBundle. Basically you get the bundle using its name without the '.properties'
private static final ResourceBundle resource = ResourceBundle.getBundle("config");
And you recover any value using this:
private final String prop = resource.getString("propName");
You need to put a PropertyPlaceholderConfigurer bean in your application context and set its location property.
See details here : http://www.zparacha.com/how-to-read-properties-file-in-spring/
You might have to modify your property file a bit for this thing to work.
Hope it helps.
I wanted an utility class which is not managed by spring, so no spring annotations like #Component, #Configuration etc. But I wanted the class to read from application.properties
I managed to get it working by getting the class to be aware of the Spring Context, hence is aware of Environment, and hence environment.getProperty() works as expected.
To be explicit, I have:
application.properties
mypath=somestring
Utils.java
import org.springframework.core.env.Environment;
// No spring annotations here
public class Utils {
public String execute(String cmd) {
// Making the class Spring context aware
ApplicationContextProvider appContext = new ApplicationContextProvider();
Environment env = appContext.getApplicationContext().getEnvironment();
// env.getProperty() works!!!
System.out.println(env.getProperty("mypath"))
}
}
ApplicationContextProvider.java (see Spring get current ApplicationContext)
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
#Component
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext CONTEXT;
public ApplicationContext getApplicationContext() {
return CONTEXT;
}
public void setApplicationContext(ApplicationContext context) throws BeansException {
CONTEXT = context;
}
public static Object getBean(String beanName) {
return CONTEXT.getBean(beanName);
}
}
[project structure]: http://i.stack.imgur.com/RAGX3.jpg
-------------------------------
package beans;
import java.util.Properties;
import java.util.Set;
public class PropertiesBeans {
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
public void getProperty(){
Set keys = properties.keySet();
for (Object key : keys) {
System.out.println(key+" : "+properties.getProperty(key.toString()));
}
}
}
----------------------------
package beans;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext ap = new ClassPathXmlApplicationContext("resource/spring.xml");
PropertiesBeans p = (PropertiesBeans)ap.getBean("p");
p.getProperty();
}
}
----------------------------
- driver.properties
Driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/test
username = root
password = root
----------------------------
<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">
<bean id="p" class="beans.PropertiesBeans">
<property name="properties">
<util:properties location="classpath:resource/driver.properties"/>
</property>
</bean>
</beans>
I'll recommend reading this link https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html from SpringBoot docs about injecting external configs. They didn't only talk about retrieving from a properties file but also YAML and even JSON files. I found it helpful. I hope you do too.

Can spring mvc trim all strings obtained from forms?

I know struts2 default config will trim all strings obtained from forms.
For example:
I type " whatever " in a form and submit, I will get "whatever" The string has been auto trimmed
Does spring mvc have this function too? THX.
Using Spring 3.2 or greater:
#ControllerAdvice
public class ControllerSetup
{
#InitBinder
public void initBinder ( WebDataBinder binder )
{
StringTrimmerEditor stringtrimmer = new StringTrimmerEditor(true);
binder.registerCustomEditor(String.class, stringtrimmer);
}
}
Testing with an MVC test context:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration
public class ControllerSetupTest
{
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void setup ( )
{
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
#Test
public void stringFormatting ( ) throws Exception
{
MockHttpServletRequestBuilder post = post("/test");
// this should be trimmed, but only start and end of string
post.param("test", " Hallo Welt ");
ResultActions result = mockMvc.perform(post);
result.andExpect(view().name("Hallo Welt"));
}
#Configuration
#EnableWebMvc
static class Config
{
#Bean
TestController testController ( )
{
return new TestController();
}
#Bean
ControllerSetup controllerSetup ( )
{
return new ControllerSetup();
}
}
}
/**
* we are testing trimming of strings with it.
*
* #author janning
*
*/
#Controller
class TestController
{
#RequestMapping("/test")
public String test ( String test )
{
return test;
}
}
And - as asked by LppEdd - it works with passwords too as on the server side there is no difference between input[type=password] and input[type=text]
register this property editor:
org.springframework.beans.propertyeditors.StringTrimmerEditor
Example for AnnotionHandlerAdapter:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
...
<property name="webBindingInitializer">
<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="propertyEditorRegistrar">
<bean class="org.springframework.beans.propertyeditors.StringTrimmerEditor" />
</property>
</bean>
</property>
...
</bean>
You can also use Spring's conversion service, which has the added benefit of working with <mvc:annotation-driven/> and with Spring Webflow. As with the other answers, the major downside is that this is a global change and can't be disabled for certain forms.
You'll need a converter to do the trimming
public class StringTrimmingConverter implements Converter<String, String> {
#Override
public String convert(String source) {
return source.trim();
}
}
Then define a conversion service that knows about your converter.
<bean id="applicationConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="mypackage.util.StringTrimmingConverter"/>
</list>
</property>
</bean>
and tie that in to mvc.
<mvc:annotation-driven conversion-service="applicationConversionService"/>
If you use Spring Webflow then it require a wrapper
<bean id="defaultConversionService" class="org.springframework.binding.convert.service.DefaultConversionService">
<constructor-arg ref="applicationConversionService"/>
</bean>
and a setting on your flow builder
<flow:flow-builder-services id="flowBuilderServices" conversion-service="defaultConversionService" development="true" validator="validator" />
Just customized the above code in order to adjust to Spring Boot, if you want to explicit trim function for some fields in the form, you can show them as below:
#Component
#ControllerAdvice
public class ControllerSetup {
#InitBinder({"dto", "newUser"})
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
binder.registerCustomEditor(String.class, "userDto.username", new StringTrimmerEditor(false));
binder.registerCustomEditor(String.class, "userDto.password", new DefaultStringEditor(false));
binder.registerCustomEditor(String.class, "passwordConfirm", new DefaultStringEditor(false));
}
}
You can user a Spring-MVC Interceptor
public class TrimInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Enumeration<String> e = request.getParameterNames();
while(e.hasMoreElements()) {
String parameterName = e.nextElement();
request.setParameter(parameterName, request.getParameter(parameterName).trim());
}
return true;
}
And set up your HandlerMapping interceptors property
<bean id="interceptorTrim" class="br.com.view.interceptor.TrimInterceptor"/>
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" p:interceptors-ref="interceptorTrim"/>
}
Or use a Servlet Filter
first,trim requestparam which is String,you can create a class and implimplements WebBingdingInitializer
#ControllerAdvice
public class CustomWebBindingInitializer implements WebBindingInitializer {
#InitBinder
#Override
public void initBinder(WebDataBinder webDataBinder, WebRequest webRequest) {
webDataBinder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
}
}
please use componentScan make this Class to be a Spring Bean.
But, I don't know how to trim the String value in requestBody JSON data.

Resources