How to get properties in JSP files using spring mvc 3 - spring

I am very new to spring mvc 3 annotation based application. I have two properties files -
WEB-INF\resources\general.properties,
WEB-INF\resources\jdbc_config.properties
Now I want to configure them through spring-servlet.xml. How I can achieve this?
In general.properties,
label.username = User Name:
label.password = Password:
label.address = Address:
...etc
jdbc_config.properties,
app.jdbc.driverClassName=com.mysql.jdbc.Driver
app.jdbc.url=jdbc:mysql://localhost:[port_number]/
app.jdbc.username=root
app.jdbc.password=pass
---etc
If I want to get label.username and app.jdbc.driverClassName in my jsp page, how do I code for them?
I also want to access these properties values from my service. How to get these property values using respective keys in method level in service class or controller class?

You need to distinguish between application properties (configuration) and localisation messages. Both use JAVA properties files, but they serve different purpose and are handled differently.
Note: I am using Java based Spring configuration in the examples bellow. The configuration can be easily made in XML as well. Just check Spring's JavaDoc and reference documentation.
Application Properties
Application properties should be loaded as property sources within your application context. This can be done via #PropertySource annotation on your #Configuration class:
#Configuration
#PropertySource("classpath:default-config.properties")
public class MyConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Then you can inject properties using #Value annotation:
#Value("${my.config.property}")
private String myProperty;
Localisation Messages
Localisation messages is a little bit different story. Messages are loaded as resource bundles and a special resolution process is in place for getting correct translation message for a specified locale.
In Spring, these messages are handled by MessageSources. You can define your own for example via ReloadableResourceBundleMessageSource:
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("/WEB-INF/messages/messages");
return messageSource;
}
You can access these messages from beans if you let Spring inject MessageSource:
#Autowired
private MessageSource messageSource;
public void myMethod() {
messageSource.getMessage("my.translation.code", null, LocaleContextHolder.getLocale());
}
And you can translate messages in your JSPs by using <spring:message> tag:
<spring:message code="my.translation.code" />

I ended up using Environment
Add these lines to config
#PropertySource("classpath:/configs/env.properties")
public class WebConfig extends WebMvcConfigurerAdapter{...}
You can get the properties from controller using autowired Environment
public class BaseController {
protected final Logger LOG = LoggerFactory.getLogger(this.getClass());
#Autowired
public Environment env;
#RequestMapping("/")
public String rootPage(ModelAndView modelAndView, HttpServletRequest request, HttpServletResponse response) {
LOG.debug(env.getProperty("download.path"));
return "main";
}
}

Firstly import spring tag lib:
<%# taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
Than import property from your application.properties
<spring:eval var="registration_url" expression="#environment.getProperty('service.registration.url')"/>
Than use your variable
test

Related

How to access Configuration objects in Spring Boot

Spring Boot has a mechanism for accessing the contents of .properties (or YAML) files that one might want to include in an application.
I currently have a dbase.properties file (residing in src/main/resources) that contains the following information:
app.dbase.name=MyDbase
app.dbase.connect=jdbc:postgresql://localhost:5432
app.dbase.user=auser
app.dbase.password=mypassword
As described in various Spring Boot documents and examples, I have a configuration class that is defined below:
#Configuration
#PropertySource("dbase.properties")
#ConfigurationProperties(prefix = "app.dbase")
public class DbInfo
{
private String name;
private String connect;
private String user;
private String password;
// Getters and setters left out for brevity
}
Unfortunately, while the various documents and examples give good information on how to define a configuration
class, I have been unable to find any description on how to use it! Apparently, a Spring Boot web application
creates an instance of a configuration class upon startup (and it looks like it also initializes them with the
values from the properties file) but my attempts to guess how to access its contents when I need to have failed.
The method of doing so is probably simple, but no one seems to want to describe this method anywhere.
So: how does one access and use one of these configuration classes once they are instantiated?
Note that #ConfigurationProperties would require all of the properties in your file to be prefixed with 'app.dbase', as in 'app.dbase.username' and 'app.dbase.password'. If that's the case, the class you have now should work.
You would call it like this:
#Component
public class Component {
#Autowired DbInfo dbInfo;
public method() {
String username = dbInfo.username();
}
}
If you are having issues, you may be required to add this to a Configuration class:
#Configuration
public class Config {
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
...
}
You may also need to add 'classpath:' inside your annotation, as in: #PropertySource("classpath:dbase.properties"), assuming your properties file is in your src/main/resources.

How to change thymeleaf static content default path in spring boot

I want to change CSS and JS default path from the resource to something else for thymeleaf.
I am using JSP as a view instead of thymeleaf but for email template, I decided to go with thymeleaf, in every search I saw spring boot by default looks into resource /static folder is there any way to force spring boot to look into another folder outside resource.
If you have multiple resource folder you can add those in your classpath by extending WebMvcConfigurerAdapter class like below. have a try
#Configuration
#EnableWebMvc
#ComponentScan
public class WebConfig extends WebMvcConfigurerAdapter {
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
String[] strBaseNames = {
"ca.gc.myproject.global.myResources", //full class path of your folder
"ca.gc.myproject.user.yourResources",
};
return messageSource;
}
}
source :https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot

How are components managed in Spring MVC and how to inject a customized component in Spring 3.2.5?

I’m considering to replace the DefaultSessionAttributeStore implementation of Spring MVC 3.2.5 with some class of my own, and I’ve known from the source code that in my 3.2.5 spring source, it’s SessionAttributesHandler which possesses a SessionAttributeStore interface reference and invokes the session store function. My question is how to replace that by DI? The SessionAttributesHandler holds a final private sessionAttributeStore reference and can only be set by the constructor:
public class SessionAttributesHandler {
...
private final SessionAttributeStore sessionAttributeStore;
...
public SessionAttributesHandler(Class<?> handlerType, SessionAttributeStore sessionAttributeStore) {
Assert.notNull(sessionAttributeStore, "SessionAttributeStore may not be null.");
this.sessionAttributeStore = sessionAttributeStore;
SessionAttributes annotation = AnnotationUtils.findAnnotation(handlerType, SessionAttributes.class);
if (annotation != null) {
this.attributeNames.addAll(Arrays.asList(annotation.value()));
this.attributeTypes.addAll(Arrays.<Class<?>>asList(annotation.types()));
}
for (String attributeName : this.attributeNames) {
this.knownAttributeNames.put(attributeName, Boolean.TRUE);
}
}
...
}
Are all the components of spring mvc managed in the spring DI container? How to inject my own SessionAttributeStore implementation into SessionAttributesHandler? What does the "Class handlerType" argument mean in the constructor? From source, it seems like it's the "controller" class. Since SessionAttributesHandler is invoked and held by a ModelFactory, and in ModelFactory there is no code instantiating the SessionAttributesHandler, is there any "XML" bean configuration file for the Spring MVC inner components and how to overwrite them?
If you want to provide your own implementation of a SessionAttributeStore you need to manually configure the RequestMappingHandlerAdapter and set your custom implementation on there. That will take care of using it through-out the rest of the infrastructure.
Assuming that you use java config you can do the following
#Configuration
public class MyConfiguration extend WebMvcConfigurationSupport {
#Bean
public SessionAttributeStore sessionAttributeStore() {
return new MyCustomSessionAttributeStore();
}
#Override
#Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
RequestMappingHandlerAdapter rmha = super.requestMappingHandlerAdapter();
rmha.setSessionAttributeStore(sessionAttributeStore());
return rmha;
}
}
If you want to do this in XML you either have to write a BeanPostProcessor which sets it on the default RequestMappingHandlerAdapter instance created by <mvc:annotation-driven /> or configure it manually and drop the namespace support.

#Value not resolved when using #PropertySource annotation. How to configure PropertySourcesPlaceholderConfigurer?

I have following configuration class:
#Configuration
#PropertySource(name = "props", value = "classpath:/app-config.properties")
#ComponentScan("service")
public class AppConfig {
and I have service with property:
#Component
public class SomeService {
#Value("#{props['some.property']}") private String someProperty;
I receive error when I want to test the AppConfig configuration class with
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.String service.SomeService.someProperty; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property 'props' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext'
The issue is documented in SPR-8539
but anyway I cannot figure out how to configure PropertySourcesPlaceholderConfigurer to get it work.
Edit 1
This approach works well with xml configuration
<util:properties id="props" location="classpath:/app-config.properties" />
but I want to use java for configuration.
as #cwash said;
#Configuration
#PropertySource("classpath:/test-config.properties")
public class TestConfig {
#Value("${name}")
public String name;
//You need this
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
If you use #PropertySource, properties have to be retrieved with:
#Autowired
Environment env;
// ...
String subject = env.getProperty("mail.subject");
If you want to retrieve with #Value("${mail.subject}"), you have to register the prop placeholder by xml.
Reason:
https://jira.springsource.org/browse/SPR-8539
I found the reason #value was not working for me is, #value requires PropertySourcesPlaceholderConfigurer instead of a PropertyPlaceholderConfigurer. I did the same changes and it worked for me, I am using spring 4.0.3 release. I configured this using below code in my configuration file.
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
Don't you need a method on your #Configuration class that returns PropertySourcesPlaceholderConfigurer, annotated #Bean and is static, to register any #PropertySource with Spring?
http://www.baeldung.com/2012/02/06/properties-with-spring/#java
https://jira.springsource.org/browse/SPR-8539
I had the very same problem. #PropertySource is not playing well with #Value. A quick workaround is to have an XML configuration which you'll refer to it from your Spring Java Configuration using #ImportResource as usual and that XML configuration file will include a single entry: <context:property-placeholder /> (of course with the needed namespace ceremony). Without any other change #Value will inject properties in your #Configuration pojo.
This can also be configured in java this way
#Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
configurer.setIgnoreUnresolvablePlaceholders(true);
configurer.setIgnoreResourceNotFound(true);
return configurer;
}
That looks mighty complicated, can't you just do
<context:property-placeholder location="classpath:some.properties" ignore-unresolvable="true"/>
then in code reference:
#Value("${myProperty}")
private String myString;
#Value("${myProperty.two}")
private String myStringTwo;
where some.properties looks something like this
myProperty = whatever
myProperty.two = something else\
that consists of multiline string
For java based config you can do this
#Configuration
#PropertySource(value="classpath:some.properties")
public class SomeService {
And then just inject using #value as before
Since Spring 4.3 RC2 using PropertySourcesPlaceholderConfigurer or <context:property-placeholder> is not needed anymore. We can use directly #PropertySource with #Value. See this Spring framework ticket
I have created a test application with Spring 5.1.3.RELEASE.
The application.properties contains two pairs:
app.name=My application
app.version=1.1
The AppConfig loads the properties via #PropertySource.
package com.zetcode.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
#Configuration
#PropertySource(value = "application.properties", ignoreResourceNotFound = true)
public class AppConfig {
}
The Application injects the properties via #Value and uses them.
package com.zetcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
#ComponentScan(basePackages = "com.zetcode")
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
#Value("${app.name}")
private String appName;
#Value("${app.version}")
private String appVersion;
public static void main(String[] args) {
var ctx = new AnnotationConfigApplicationContext(Application.class);
var app = ctx.getBean(Application.class);
app.run();
ctx.close();
}
public void run() {
logger.info("Application name: {}", appName);
logger.info("Application version: {}", appVersion);
}
}
The output is:
$ mvn -q exec:java
22:20:10.894 [com.zetcode.Application.main()] INFO com.zetcode.Application - Application name: My application
22:20:10.894 [com.zetcode.Application.main()] INFO com.zetcode.Application - Application version: 1.1
The thing is: as far as I get it, <util:propertes id="id" location="loc"/>, is just a shorthand for
<bean id="id" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="loc"/>
</bean>
(see documentation of util:properties). Thus, when you use util:properties, a standalone bean is created.
#PropertySource, on the other hand, as documentation says is an
annotation providing a convenient and declarative mechanism for
adding a PropertySource to Spring's Environment'.
(see #PropertySource doc). So it doesn't create any bean.
Then "#{a['something']}" is a SpEL expression (see SpEL), that means "get something from bean 'a'". When util:properties is used, the bean exists and the expression is meaningful, but when #PropertySource is used, there is no actual bean and the expression is meaningless.
You can workaround this either by using XML (which is the best way, I think) or by issuing a PropertiesFactoryBean by yourself, declaring it as a normal #Bean.
Another thing that may be happening: ensure your #Value annotated values are not static.
In my case, depends-on="bean1" was within property-placeholder was causing the issue. I removed that dependency and used #PostConstruct to achieve the same original functionality and was able to read the new values too.
If you are configuring with xml, after adding
<context:property-placeholder location="..."/>
Make sure your annotations are activated. In my case properties were not fetched for this reason:
<context:annotation-config/>
for me it worked
spring.cloud.config.server.git.default-label=main
spring.cloud.config.server.native.searchLocations=file:///Users/${your username}/Projects/git-local-repositories/
spring.profiles.active=native

Convert Spring bean configuration into XML configuration

i am working on BIRT reporting tool. which is need to called by spring MVC.
i got one example from spring which is here. in this example, configuration is done via bean. can anyone help me convert this configuration in to xml based configuration ?
#EnableWebMvc
#ComponentScan({ "org.eclipse.birt.spring.core","org.eclipse.birt.spring.example" })
#Configuration
public class BirtWebConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/reports").setViewName("birtView");
}
#Bean
public BirtView birtView() {
BirtView bv = new BirtView();
// bv.setReportFormatRequestParameter("ReportFormat");
// bv.setReportNameRequestParameter("ReportName");
bv.setBirtEngine(this.engine().getObject());
return bv;
}
#Bean
public BeanNameViewResolver beanNameResolver() {
BeanNameViewResolver br = new BeanNameViewResolver();
return br;
}
#Bean
protected BirtEngineFactory engine() {
BirtEngineFactory factory = new BirtEngineFactory();
return factory;
}
}
I wants a similar configuration in xml file.
There's really no tool for extracting Spring annotations to Spring bean context xml file. You'll have to do it by hand, shouldn't be too hard as all the Spring annotations functionality can be duplicated into Spring context xml tags.
if you want to use spingmvc, so no need the configuration files.
my solution is that in Birt Script i call the impl java file like this :
sampleService = new Packages.com.example.warlock.service.SampleServiceImpl();
pojo = new Packages.com.example.warlock.entity.Sample();
iterator = sampleService.getSamples().iterator();
because my SampleService is a interface and SampleServiceImpl is impl java, the two java file are not config as #Bean.
At first i want to get the data from ModelMap but failed, so i skip the controller and straight to call Service, then final call the DAO to get the Data from DB

Resources