How to use velocity 1.7 with Spring - spring

I am using velocity 1.7 withe spring 3.1 framework for sending email. velocity is used for email templates.
Below is the configuration
<bean id="velocityEngine"
class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<props>
<prop key="resource.loader">class</prop>
<prop key="class.resource.loader.class">
org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
</prop>
</props>
</property>
</bean>
and below is my code
#Component
public class EmailUtils {
#Autowired
private static VelocityEngine velocityEngine;
public static void sendMail(String subject, Map data, String template,
String toName, String toAddress) {
HtmlEmail email = new HtmlEmail();
try {
email.setHostName(hostName);
email.setSmtpPort(smtpPort);
email.setSubject(subject);
System.out.println(template +" template");
System.out.println(data +" data ");
System.out.println(velocityEngine +" velocityEngine ");
String message = VelocityEngineUtils.mergeTemplateIntoString(
velocityEngine, template, data);
System.out.println(message +" message message ");
email.setMsg(message);
email.addTo(toAddress, toName);
email.setFrom(fromAddress, fromName);
email.send();
} catch (EmailException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
When I run the application I get following error.
java.lang.NullPointerException
at org.springframework.ui.velocity.VelocityEngineUtils.mergeTemplate(VelocityEngineUtils.java:58)
as the velocity engine is null.
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<bean id="velocityEngine"
class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<props>
<prop key="resource.loader">class</prop>
<prop key="class.resource.loader.class">
org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
</prop>
</props>
</property>
</bean>
Please help me. Is there any other configuration that I need to do?

I had the same issue when using . I could have solved it in the following way:
#Configuration
public class ApplicationConfiguration {
#Bean
public VelocityEngine getVelocityEngine() throws VelocityException, IOException{
VelocityEngineFactory factory = new VelocityEngineFactory();
Properties props = new Properties();
props.put("resource.loader", "class");
props.put("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
factory.setVelocityProperties(props);
return factory.createVelocityEngine();
}
}
But instead - because I was using velocity templates for my views and had already declared a VelocityConfigurer, so I instead Autowired in my declaration of VelocityConfigurer and called getVelocityEngine() on that.
I did discover that, if it's being autowired into #Service-s or #Component-s and you've declared in a shared applicationContext.xml file, then the xml declaration had to be in that shared applicationContext.xml as well rather than the xxx-servlet.xml config.
I think this is because applicationContext.xml is shared amongst all servlets in the application, so it has to be fully processed before the xxx-servlet.xml files are.
Alternatively, you could enable spring bean factory debugging and see if it's having any issues instantiating it:
log4j.category.org.springframework.beans.factory=DEBUG

I think you cannot use #Autowired with a static field. You can work around this with a non-static setter:
#Autowired
public void setVelocityEngine(VelocityEngine ve) {
EmailUtils.velocityEngine = ve;
}
or in another way but I would strongly recommend turning EmailUtils into a non-static bean. Spring handles non-static components much better (no ugly hacks needed), it will be possible to swap implementations and your code will stick to DI philosphy.

This is my attempt, I initialize the "velocityEngine" bean manually via ClassPathXmlApplicationContext:
Spring application-context.xml
<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<value>
resource.loader=class
class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
</value>
</property>
</bean>
This is my template_text.vm, put it in the classpath, same level as application-context.xml.
Dear $userName,
You have made the following request on $userTime.
#if( $isFileMissing )
Missing file(s) found in home directory:
#foreach( $missingFile in $missingFiles )
- $missingFile
#end
#end
Best regards,
This is the Java code:
public static void main(String[] args) throws Exception {
String[] springConfig = {"application-context.xml"};
org.springframework.context.ApplicationContext context = new org.springframework.context.support.ClassPathXmlApplicationContext(springConfig);
java.util.Map<String, Object> model = new java.util.HashMap<String, Object>();
model.put("userName", "John Low");
model.put("userTime", "2015-10-28 23:59:59");
model.put("isFileMissing", true);
model.put("missingFiles", new String[] {"line 1", "line 2", "line 3"});
String text = org.springframework.ui.velocity.VelocityEngineUtils.mergeTemplateIntoString((VelocityEngine)context.getBean("velocityEngine"), "/template_text.vm", "UTF-8", model);
System.out.println(text);
}
The output:
Dear John Low,
You have made the following request on 2015-10-28 23:59:59.
Missing file(s) found in home directory:
- file 1
- file AAA
- line 3
Best regards,

I had the same issue when I was upgrading our project to Java 11 + Spring Boot 2.1.8. I could have solved it in the following way:
#Configuration
public class AppConfig {
#Bean
public VelocityEngine velocityEngine() throws Exception {
Properties properties = new Properties();
properties.setProperty("input.encoding", "UTF-8");
properties.setProperty("output.encoding", "UTF-8");
properties.setProperty("resource.loader", "class");
properties.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
VelocityEngine velocityEngine = new VelocityEngine(properties);
return velocityEngine;
}
}

Related

#Value in my spring controller does not work

My controller has
#Value("${myProp}")
private String myProp;
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
#RequestMapping(value = "myProp", method = RequestMethod.GET)
public #ResponseBody String getMyProp(){
return "The prop is:" + myProp;
}
my applicationcontext.xml has
<bean id="appConfigProperties" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="location" value="classpath:MyApps-local.properties" />
</bean>
I get the following exception:
Caused by: java.lang.IllegalArgumentException: Could not resolve
placeholder 'myProp' in string value "${myProp}"
Note: My properties file MyApps-local.properties is in the classpath and contains
myProp=delightful
any help would be great....
In XML based configuration you need to use PropertyPlaceholderConfigurer bean
<beans xmlns="http://www.springframework.org/schema/beans" . . . >
. . .
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:database.properties" />
</bean>
. . .
</beans>
but you can use values from database.properties in xml configuration only
<beans xmlns="http://www.springframework.org/schema/beans" . . >
. . .
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
. . .
</beans>
If you want to use values from properties files inside #Value annotation for bean's fields, you need to add #Confuguration and #PropertySource annotation to bean class. Like this
#Configuration
#PropertySource("classpath:database.properties")
public class AppConfig {
#Value("${jdbc.url}")
private String url;
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
}
In your configuration you have two PropertySourcesPlaceholderConfigurer. The first one define in the DispatcherServlet using Java #Configuration uses the standard environment to find properties. This means properties from system environment and environment variables as well as an defined #PropertySource.
This is not aware of your MyApps-local.properties file specified in the applicationContext.xml. The second PropertySourcesPlaceholderConfigurer in the xml file is aware of the MyApps-local.properties file but it only post process placeholder in the root application context
bean factory post processors are scoped per application context.
Change you web application context to specify the property source.This will add the properties in the file to your environment
#Configuration
#PropertySource("classpath:MyApps-local.properties")
public class WebConfig{
#Autowired
private Environment env;
#RequestMapping(value = "myProp", method = RequestMethod.GET)
public #ResponseBody String getMyProp(){
return "The prop is:" + env.getProperty("myProp");
}
}
In this case you dont need the PropertySourcesPlacheholder as you can query for he properties from the environment. Then keep your applicationContext.xml as is
It will also work with the PropertySourcesPlaceholder #Bean as it also picks properties from the enviroment. However the abover is clean than below
#Configuration
#PropertySource("classpath:MyApps-local.properties")
public class WebConfig{
#Value("${myProp}")
private String myProp;
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
#RequestMapping(value = "myProp", method = RequestMethod.GET)
public #ResponseBody String getMyProp(){
return "The prop is:" + myProp;
}
}
See if this helps
You could go on and use this util tag in your xml configuration
<util:properties id="appConfigProperties" location="location to your properties file" />
<context:property-placeholder properties-ref="appConfigProperties" />
Comes from schema
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
Then in you code where you want your value from property file use it as
#Value("${myPropl}")
private String str;
works for me, let me know if stuck any where :)
Read carefully this http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-application-property-files
For dev-mode use profile-specific properties

Unitils: How can it obtain database properties from Spring

I am using Unitils with Spring for unit testing. I've configured Spring with datasource using a properties file.
My question is how can I use the same datasource or the same properties for Unitils?
Unitils expects a file in the classpath unitils.properties with database configuration parameters like url, user, password and driver.
I've tried to configure Unitils using the properties used in the Spring configuration as below but it is not working.
database.driverClassName=${jdbc.driver.class}
Thanks,
Adi
One potential solution... You could have your Spring configuration read its datasource parameters from the unitils.properties, instead of the other way around. Probably not ideal.
I believe unitils is using spring under the covers, so you might also try adding your datasource context in your unitils tests by using #SpringApplicationContext. If you could figure out the name of the datasource bean setup by unitils when it starts up, you could override it in your context (assuming the unitils datasource bean is created before the other spring beans are which may/may not be true.)
e.g.
#SpringApplicationContext({"correctDataSourceContext.xml"})
EDIT: Another option that will definitely work: https://stackoverflow.com/a/6561782/411229
Basically instantiate Unitils yourself and set the properties manually.
Ryan answer is correct and helpful as well though I've used different approach.
I extended the class PropertiesDataSourceFactory ro override the methods as follows:
public class UnitilsDataSourceFactory extends PropertiesDataSourceFactory {
#Override
public void init(Properties configuration) {
try {
String[] configFiles = new String[] { "applicationContext-test.xml" };
BeanFactory factory = new ClassPathXmlApplicationContext(configFiles);
SystemPropertiesReader systemPropertiesReader = (SystemPropertiesReader) factory.getBean("systemPropertiesReader");
Properties loadProperties = systemPropertiesReader.loadProperties();
super.init(loadProperties);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public DataSource createDataSource() {
DataSource dataSource = super.createDataSource();
return dataSource;
}
}
and also wrote a SystemPropertiesReader as:
public class SystemPropertiesReader {
private Collection<Resource> resources;
public void setResources(final Collection<Resource> resources) {
this.resources = resources;
}
public void setResource(final Resource resource) {
resources = Collections.singleton(resource);
}
#PostConstruct
public Properties loadProperties() throws Exception {
final Properties systemProperties = System.getProperties();
for (final Resource resource : resources) {
final InputStream inputStream = resource.getInputStream();
try {
systemProperties.load(inputStream);
} finally {
//
}
}
return systemProperties;
}
}
and added a bean with the properties file:
<bean id="systemPropertiesReader" class="uk.co.friendslife.eventmanager.domain.dao.SystemPropertiesReader">
<property name="resource">
<value>classpath:/META-INF/em/config/eventmanager_${database_name_lower}.properties</value>
</property>
</bean>
add the following to unitils.properties:
org.unitils.database.config.DataSourceFactory.implClassName=x.y.UnitilsDataSourceFactory
Just want to add some idea and im not sure if it is a best practice or not so correct me if theres something wrong.
MYPROJECT
-src
--TestPackage
---BaseServiceTest.class
---BlogspotServiceTest.class
--hibernate.cfg.xml
-web
--WEB-INF
---blogspot-servlet-test.xml
---jdbc-test.properties
in my case I used my blogspot-servlet-test.xml to call or to create the datasource
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
.... some bean configuration
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="file:web/WEB-INF/jdbc.properties"/>
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- DAO'S -->
<bean id="blogspotDAO" class="package.BlogspotDAOImpl"/>
<!-- SERVICES -->
<bean id="blogspotService" class="package.BlogspotServiceImpl"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
MY jdbc-test.properties file
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.dialect=org.hibernate.dialect.MySQL5Dialect
jdbc.databaseurl=jdbc:mysql://127.0.0.1:3306/dbspringminiblogtest
jdbc.username=root
jdbc.password=
For hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd//hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<mapping class="somePackage.entity.Author"/>
<!-- Other Entity Class to be mapped -->
</session-factory>
</hibernate-configuration>
and i created BaseClass for me to lessen creating of multiple #SpringApplicationContext annotation and it is also use to configure common configuration needed in testing other class, just extends it.
#SpringApplicationContext({"file:web/WEB-INF/blogspot-servlet-test.xml"})
public class BaseServiceTest extends UnitilsJUnit4 {
}
i used #SpringApplicationContext to load the datasource and other bean configurations on my BaseClass and this is how i implement it.
Below : see Spring-Unitils Tutorial
for more details
public class BlogspotServiceTest extends BaseServiceTest{
#Mock
#InjectInto(property = "blogspotDAO")
#SpringBean("blogspotDAO")
private BlogspotDAO blogspotDAOMock;
#TestedObject
#SpringBean("blogspotService")
private BlogspotService blogspotServiceMock;
#Test
public void testAddBlogSpot() {
assertNotNull("BlogspotService Not null",blogspotServiceMock);
}
}
NOTE: please create unitils.properties and unitils-local.properties inside TestPackage to be able to run the program.
For #SpringBean explanation and other annotation please read :
Unitils-EasyMock

Spring 3.1.1 java based configuration issue of FreeMarkerConfigurer

I am using Spring 3.1.1 with Freemarker.
After I have successded to use the new concept of java based configuraion of the new spring 3.1.
Now I try to use Freemarker with it.
However,I got that exception:
javax.servlet.ServletException: Could not resolve view with name
'/welcome' in servlet with name 'appServlet'
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1139)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:927)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
Here is the WebConfig:
package com.springway.config;
#Configuration
#ComponentScan("com.springway")
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Inject
private Environment environment;
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJacksonHttpMessageConverter());
}
#Bean
public ViewResolver viewResolver() {
UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
viewResolver.setViewClass(FreeMarkerView.class);
return viewResolver;
}
#Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath(
"/WEB-INF/freemarker.xml");
return configurer;
}
freemarker.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- freemarker config -->
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
<property name="freemarkerSettings">
<props>
<prop key="number_format">0.######</prop>
</props>
</property>
<property name="freemarkerVariables">
<map>
<entry key="xml_escape" value-ref="fmXmlEscape"/>
</map>
</property>
</bean>
<bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape"/>
<!--
View resolvers can also be configured with ResourceBundles or XML files. If you need
different view resolving based on Locale, you have to use the resource bundle resolver.
-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".ftl"/>
</bean>
</beans>
The controller :
#RequestMapping(value="/", method=RequestMethod.GET)
public ModelAndView home(Principal user) {
return new ModelAndView("/welcome.ftl");
}
I am struggling the same problem as yours. And I tried to turn on logging level "DEBUG" for "org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer". I found following message:
java.io.FileNotFoundException: ServletContext resource [/WEB-INF/freemarker/] cannot be resolved to URL because it does not exist
at org.springframework.web.context.support.ServletContextResource.getURL(ServletContextResource.java:154) ~[spring-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]
at org.springframework.web.context.support.ServletContextResource.getFile(ServletContextResource.java:169) ~[spring-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]
at org.springframework.ui.freemarker.FreeMarkerConfigurationFactory.getTemplateLoaderForPath(FreeMarkerConfigurationFactory.java:351) [spring-context-support-3.1.1.RELEASE.jar:3.1.1.RELEASE]
at org.springframework.ui.freemarker.FreeMarkerConfigurationFactory.createConfiguration(FreeMarkerConfigurationFactory.java:304) [spring-context-support-3.1.1.RELEASE.jar:3.1.1.RELEASE]
.....
And a wired log from Jetty:
WARN org.eclipse.jetty.util.log - /freemarker/
I don't know what going on! So that I replaced the value of "templateLoaderPath" with another name, like "/WEB-INF/tmpl-freemarker/", then everything is workable!!
Next, I tried to use ServerContext.getResource() to test "/WEB-INF/freemarker/html.ftl". Here is the result:
Resource under /WEB-INF/freemarker/: null
My code of testing:
#Inject
private ServletContext servletContext;
try {
logger.info("Resource under /WEB-INF/freemarker/: {}", servletContext.getResource("/WEB-INF/freemarker/html.ftl"));
} catch(Exception e) {
logger.info("Exception while getResource", e);
}
It seems ServletContext can't find out the resource under "/WEB-INF/freemarker/" correctly either. But I'm not sure the object of ServletContext of Spring is as same as one on normal environment of Java Servlet.
I'm using FreeMarker 2.3.19, Springframework 3.1.1.RELEASE, and jetty-maven-plugin 7.4.5.v20110725 of Maven.
#Configuration
#EnableWebMvc
#ImportResource("classpath:/security-integration.xml")
#ComponentScan("com.springway")
public class WebConfiguration extends WebMvcConfigurerAdapter {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public FreeMarkerViewResolver viewResolver() {
FreeMarkerViewResolver freeMarkerViewResolver = new FreeMarkerViewResolver();
freeMarkerViewResolver.setCache(true);
freeMarkerViewResolver.setPrefix("");
freeMarkerViewResolver.setSuffix(".ftl");
return freeMarkerViewResolver;
}
#Bean
public FreeMarkerConfigurer freemarkerConfig() {
FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
freeMarkerConfigurer.setTemplateLoaderPath("/WEB-INF/freemarker/");
Properties settings = new Properties();
settings.setProperty("number_format", "0.######");
freeMarkerConfigurer.setFreemarkerSettings(settings);
Map variables = new java.util.HashMap<String, Object>();
variables.put("xml_escape", new XmlEscape());
freeMarkerConfigurer.setFreemarkerVariables(variables);
return freeMarkerConfigurer;
}
}
You might have done wrong import
import org.springframework.web.portlet.ModelAndView;
instead of do this
import org.springframework.web.servlet.ModelAndView;

No bean named 'errorNotifier' is defined

I'm trying to setup a bean factory in spring, something which should be really simple to do, but I just can't figure out why it's not working. Spend most of today looking at examples, reading other similar posts on stackOverflow, reading Spring In Action as well as Spring Recipes with no success so far. A second pair of eyes will probably pick up my mistake in no time.
Error Notifier Interface
public interface ErrorNotifier {
public void notifyCopyError(String srcDir, String destDir, String filename);
}
Error Notifier Implementation
public class EmailErrorNotifier implements ErrorNotifier {
private MailSender mailSender;
/**
* Blank constructor
*/
public EmailErrorNotifier() {
}
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
#Override
public void notifyCopyError(String srcDir, String destDir, String filename) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("system#localhost");
message.setTo("admin#localhost");
message.setSubject("Finished Uploading File");
message.setText("Your upload failed!");
mailSender.send(message);
}
}
My config in applicationContext.xml
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${email.host}"/>
<property name="protocol" value="${email.protocol}"/>
<property name="port" value="${email.port}"/>
<property name="username" value="${email.username}"/>
<property name="password" value="${email.password}"/>
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
</props>
</property>
</bean>
<bean id="errorNotifier" name="errorNotifier" class="com.bdw.controller.EmailErrorNotifier">
<property name="mailSender" ref="mailSender"/>
</bean>
And the class in which I test it
public class test {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext(
ApplicationContext.CLASSPATH_ALL_URL_PREFIX
+ "applicationContext.xml");
ErrorNotifier notifier =
context.getBean("errorNotifier", ErrorNotifier.class);
notifier.notifyCopyError("test", "test", "test");
}
}
I don't get any errors in tomcat or glassfish logs, just this output:
Exception in thread "main"
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
bean named 'errorNotifier' is defined at
org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:527)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1083)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:274)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at
org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1079)
at test.main(test.java:21)
If I change context.getBean parameter to lookup mailSender, I get No bean named 'mailSender'.
Any ideas?
The applicationContext file is likely not on the class path; I'm not sure that the all_URL_prefix will dig past the root level of the filesystem and jars, making the test go wonky. Try moving the config file, or changing the list of locations from which to grab the config file.

How to inject complete propertiesfile in a springbean

I have a properties-file with a lot of values and I do not want to list them in my bean-configuration-file separately. E.g.:
<property name="foo">
<value>${foo}</value>
</property>
<property name="bar">
<value>${bar}</value>
</property>
and so on.
I imagine to inject all completely as java.util.Properties or less as a java.util.Map.
Is there a way to do so?
For Java config you can use something like this:
#Autowired #Qualifier("myProperties")
private Properties myProps;
#Bean(name="myProperties")
public Properties getMyProperties() throws IOException {
return PropertiesLoaderUtils.loadProperties(
new ClassPathResource("/myProperties.properties"));
}
You can also have multiple properties this way, if you assign a unique bean name (Qualifier) to each instance.
Yes, you can use <util:properties> to load a properties file and declare the resulting java.util.Properties object as a bean. You can then inject that as you would any other bean property.
See section C.2.2.3 of the Spring manual, and their example:
<util:properties id="myProps" location="classpath:com/foo/jdbc-production.properties"
Remember to declare the util: namespace as per these instructions.
For Java Config, use PropertiesFactoryBean:
#Bean
public Properties myProperties() {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/myProperties.properties"));
Properties properties = null;
try {
propertiesFactoryBean.afterPropertiesSet();
properties = propertiesFactoryBean.getObject();
} catch (IOException e) {
log.warn("Cannot load properties file.");
}
return properties;
}
And then, set the properties object:
#Bean
public AnotherBean myBean() {
AnotherBean myBean = new AnotherBean();
...
myBean.setProperties(myProperties());
...
}
Hope this helps for those interested in Java Config way.
It's possible with the PropertyOverrideConfigurer mechanism:
<context:property-override location="classpath:override.properties"/>
Properties file:
beanname1.foo=foovalue
beanname2.bar.baz=bazvalue
The mechanism is explained in the section 3.8.2.2 Example: the PropertyOverrideConfigurer
This is an echo of #skaffman's response in this SO question. I am adding more details to help others and myself when I try to solve this in the future.
There are three ways to inject the property file
Method 1
<bean id="myProps" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:com/foo/jdbc-production.properties</value>
</list>
</property>
</bean>
Reference ( link )
Method 2
<?xml version="1.0" encoding="UTF-8"?>
<beans
...
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="...
...
http://www.springframework.org/schema/util/spring-util.xsd"/>
<util:properties id="myProps" location="classpath:com/foo/jdbc-production.properties"/>
Reference ( link )
Method 3
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:com/foo/jdbc-production.properties" />
</bean>
Reference ( link )
Essentially, all the methods can create a Properties bean out of the properties file. You may even directly inject a value from the property file by using #Value injector
#Value("#{myProps[myPropName]}")
private String myField;

Resources