Navigate to File ==> Settings ==> Build, Exceution, Deployment ==> Gradle ==> Select Offline Work check box on the right side of the pane under Global Gradle Settings
Saturday, 24 June 2017
Sunday, 30 April 2017
How to resolve Spring Boot web application error "Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback."
If you come across any such error as like below
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
.........
There was an unexpected error (type=Not Found, status=404).
No message available
then one possible problem would be that the below class wouldn't had been created
For HTML pages use the below class
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
public class ApplicationWebMvcConfig extends WebMvcConfigurerAdapter{
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/html/");
resolver.setSuffix(".html");
return resolver;
}
}
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
.........
There was an unexpected error (type=Not Found, status=404).
No message available
then one possible problem would be that the below class wouldn't had been created
For HTML pages use the below class
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
public class ApplicationWebMvcConfig extends WebMvcConfigurerAdapter{
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/html/");
resolver.setSuffix(".html");
return resolver;
}
}
For JSP pages use the below class
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
public class ApplicationWebMvcConfig extends WebMvcConfigurerAdapter{
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
}
Monday, 17 April 2017
How to implement Localization in Spring application
Details given below includes Thymeleaf integration but you can use the framework that applies to your application.
Following are certain requirements that are needed
Following are certain requirements that are needed
Ø Spring
Ø jQuery datepicker - (https://github.com/eternicode/bootstrap-datepicker)
Ø jQuery inputmask - (http://github.com/RobinHerbots/jquery.inputmask)
Ø Properties Files
Examples:
messages_en.properties - English
wellcome.world = Hello World !
fileName should have undrescore '_' and place it on classpath. Supported
formats and codes can be found in : http://www.oracle.com/technetwork/java/javase/javase7locales-334809.html
Spring Configuration
Ø SessionLocaleResolver
Register a
"SessionLocaleResolver" bean, name it exactly the same characters
"localeResolver". It resolves the locales by getting the predefined
attribute from user's session.
Ø LocaleChangeInterceptor
Register a
"LocaleChangeInterceptor" interceptor and refer it to any handler mapping
that need to support multiple languages. The "paramName" is the
parameter value that's used to set the locale.
In dispatcher-servlet.xml add
the below ones.
<bean
id="localeResolver"
class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale"
value="en" />
</bean>
//paramName - name of the url
parameter to hold the locale variable
<bean
id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property
name="paramName" value="language" />
</bean>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping
path="/css/**" />
<mvc:exclude-mapping
path="/js/**" />
<mvc:exclude-mapping
path="/bootstrap/**" />
<mvc:exclude-mapping
path="/img/**" />
<mvc:exclude-mapping
path="/fonts/**" />
<bean
class="com..sk.tol.base.view.config.UserInterceptor" />
</mvc:interceptor>
<ref
bean="localeChangeInterceptor"/>
</mvc:interceptors>
This will enable us to change
locale simply by passing language parameter in url:
http://localhost:8080/appname/welcome.htm?language=en For example like this:
<a
href="?language=en">English</a>
Below things needs to be taken care of
LocaleUtils.java
Just write a utility class which help us to obtain various locale based formats, patterns.
jQuery Datepicker
Properties Files
jQuery Datepicker has its own
objects with language settings, like name of the days, months, etc... which are defined in
separate.js files and we need to include corresponding script of every
language that we will be using in the application.
<script
src="js/jquery.wait.js"
th:src="@{/js/locales/bootstrap-datepicker.sk.min.js}"></script>
<script
src="js/jquery.wait.js"
th:src="@{/js/locales/bootstrap-datepicker.en-GB.min.js}"></script>
LocaleSettings html element
We have to define one invisible
element that will hold various locale related information, so we can access it
from html, javaScript/jQuery.
Place it somewhere on top
of html hierarchy, so you can access it from every page you need to. In the
code below you can see that we are storing the information in html data
attributes with the help of Thymeleaf 'th:attr' to call our LocaleUtil java
class.
<div
id="localeSettings" class="ext-default-hidden"
th:attr="data-decimal-separator=${@localeUtil.getDecimalSeparator()}, data-thousands-separator=${@localeUtil.getGroupingSeparator()},
data-locale=${#ctx.locale}">
</div>
Initialization and use
When initializing datecipicker,
we only need to provide it with locale code, that we can take from our
localeSetting element:
var locale =
$("#localeSettings").data("locale");
$('.ext-datepicker,#ext-datepicker').datepicker({
orientation: "bottom
auto",
language:
locale
})
The property file should hold datepicker.date.format property name and for English
language with its message_en.properties file: datepicker.date.format=M d, yyyy
Assigning the format to datepicker
element through thymeleaf
<div
th:attr="data-date-format=#{datepicker.date.format}"
class="ext-datepicker input-append date input-group">
<input
type="datetime" class="span2 form-control ext-readonly-white
add-on" th:field="*{createDateFrom}" />
<div
class="input-group-addon add-on">
<i
class="fa fa-calendar"></i>
</div>
</div>
jQuery inputmask
Example of Initialization of
inputmask for all elements with class "positive-amount-nullable":
var cfgDefaults =
{
thousandsSeparator:
",",
decimalSeparator: "."
};
function init(){
var $elm = $("#localeSettings");
cfgDefaults.decimalSeparator =
$elm.data("decimal-separator");
cfgDefaults.thousandsSeparator =
$elm.data("thousands-separator");
};
$(".positive-amount-nullable").off("inputmask").inputmask("currency",
{
removeMaskOnSubmit: true,
placeholder: " ",
prefix: "",
allowPlus: false,
allowMinus: false,
groupSeparator:
cfgDefaults.thousandsSeparator,
radixPoint: cfgDefaults.decimalSeparator
}
);
Now we only need to assign css
class "positive-amount-nullable" to input we want to get formatted.
Example:
<input
type="text" class="form-control positive-amount-nullable"
th:field="*{transactionAmount}" />
Serialization / Deserialization in dto's date fields
To enable spring automatic
serialization/deserialization just annotate the Date fields as follows. You can
use provided custom (de)serializers.
You can also make your
own (de)serializers by extending one of AJsonLocaleDateSerializer.java or AJsonLocaleDateDeserializer.java
See java.text.DateFormat
for more info on the formats used.
@DateTimeFormat(style =
"M-")
@JsonSerialize(using =
JsonLocaleDateSerializer.class)
@JsonDeserialize(using =
JsonLocaleDateDeserializer.class)
private Date transactionDate;
@DateTimeFormat(pattern =
"HH:mm")
@JsonSerialize(using =
JsonLocaleTimeSerializer.class)
@JsonDeserialize(using =
JsonLocaleTimeDeserializer.class)
private Date transactionTime;
@JsonSerialize(using =
JsonLocaleDateTimeSerializer.class)
@JsonDeserialize(using =
JsonLocaleDateTimeDeserializer.class)
private Date
transactionDateTime;
Examples of getting various info on locales
Here are example of various
information we can get on front-end by using thymeleaf
<div
class="active" th:text="${#ctx.locale}">Current Locale
from context from session</div>
<div
class="active" th:text="${#dates.createNow()}">Thymeleaf
dates utility - gets current Date</div>
<div
class="active" th:text="${@localeUtil.formatDate(#dates.createNow())}">Current date formatted by
LocaleUtil.java</div>
<div
class="active" th:text="${@localeUtil.getDateFormatPattern()}">Get date pattern from
LocaleUtil.java</div>
<div
class="active" th:text="${@localeUtil.formatTime(#dates.create(2016,9,5,15,45,30,231))}">Current time formatted by
LocaleUtil.java</div>
<div
class="active" th:text="${@localeUtil.getTimeFormatPattern()}">Get time pattern from
LocaleUtil.java</div>
Get current Locale in spring MVC controller
@RequestMapping(value = {
"/method" }, method = RequestMethod.GET)
public String
someControllerMethod(ExampleDto dto, HttpSession session, Model m, Locale
locale ) {
// Implementation code
...
return
"someResult";
}
The current Locale can be accessed in java code by following way
Locale locale = org.springframework.context.i18n.LocaleContextHolder.getLocale();
Monday, 10 April 2017
How to retrieve data from database using spring jpa hibernate
1. Create a Specification which would construct a query to pull records from database for a particular jpa entity
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.data.jpa.domain.Specification;
public class TravelEntitySpecification {
public static Specification<TravelEntity> filterTravelEntity(final String id,final String empId) {
return new Specification<TravelEntity>() {
@Override
public Predicate toPredicate(Root<TravelEntity> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
Predicate predicate = builder.conjunction();
predicate = builder.and(predicate, builder.equal(root.<PK>get(Constant.STRING_ID).get(Constant.STRING_ID), id));
predicate = builder.and(predicate, builder.equal(root.<PK>get(Constant.STRING_ID).get(Constant.DEFV201_empId), empId));
return predicate;
}
};
}
2. Create a Repository interface as like below for the entity
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface TravelEntityRepository extends JpaRepository<TravelEntity, String>, JpaSpecificationExecutor<TravelEntity>{
}
3. Invoke the repository from the dao as like below
public class TravelDAO{
@Autowired
private TravelEntityRepository travelEntityRepository;
public List<TravelEntity> getTravelList(){
return travelEntityRepository.findAll(TravelEntitySpecification.filterTravelEntity("1","2"));
}
public TravelEntity getTravelData(){
return travelEntityRepository.findOne(TravelEntitySpecification.filterTravelEntity("2","2"));
}
Saturday, 8 April 2017
How to configure Logger in an web application
Below logback-appenders.xml helps to create log file
<included>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{ISO8601} %-5p [%t][%c:%L] %m%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${app.logs}//.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>${app.logs}//.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- keep 30 days' worth of history -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date{ISO8601} %-5p [%t][%c:%L] %m%n</pattern>
</encoder>
</appender>
</included>
Below logback-loggers.xml provides way to log spring & hibernate related content
<included>
<logger name="org.hibernate" level="WARN" />
<logger name="org.hibernate.type" level="WARN" />
<logger name="org.springframework" level="WARN" />
<logger name="org.springframework.web" level="WARN" />
<logger name="org.springframework.web.servlet" level="WARN" />
<logger name="org.hibernate.SQL" level="debug"/>
<logger name="org.hibernate.type" level="trace"/>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</included>
How to write simple Spring MVC or Spring Web Controller
Methods provided in the below class are some ways of mapping appropriate request to appropriate urls
@Controller
public class Controller {
@RequestMapping(value = { "/url" }, method = {RequestMethod.GET,RequestMethod.POST})
public String showPage(@Valid VO VO,
BindingResult bindingResult, Locale locale, Model model, HttpSession session) {
.
.
.
.
}
@RequestMapping(value = "/url", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON)
public @ResponseBody ResponseEntity<VO<vo>> searchByCriteria(
@RequestBody @Valid FormVO formVO, BindingResult bindingResult, Model m,
HttpServletRequest request) {
.
.
.
}
}
@Controller
public class Controller {
@RequestMapping(value = { "/url" }, method = {RequestMethod.GET,RequestMethod.POST})
public String showPage(@Valid VO VO,
BindingResult bindingResult, Locale locale, Model model, HttpSession session) {
.
.
.
.
}
@RequestMapping(value = "/url", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON)
public @ResponseBody ResponseEntity<VO<vo>> searchByCriteria(
@RequestBody @Valid FormVO formVO, BindingResult bindingResult, Model m,
HttpServletRequest request) {
.
.
.
}
}
How to write Interceptor in Spring MVC or Spring Web
1. Provide the below ones in the dispatcher-servlet.xml containing in your project
<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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<security:global-method-security pre-post-annotations="enabled" />
<context:component-scan base-package="com" />
<context:property-placeholder location="file:///${configs}//*.properties" file-encoding="UTF-8" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="en" />
</bean>
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="language" />
</bean>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/css/**" />
<mvc:exclude-mapping path="/js/**" />
<mvc:exclude-mapping path="/bootstrap/**" />
<mvc:exclude-mapping path="/img/**" />
<mvc:exclude-mapping path="/fonts/**" />
<bean class="com.UserInterceptor" />
</mvc:interceptor>
<ref bean="localeChangeInterceptor"/>
</mvc:interceptors>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="100000"/>
</bean>
</beans>
2.Create a interceptor class as like below
import java.security.Principal;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.ws.rs.core.HttpHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.dto.UserVO;
import com.service.AuthorizationService;
public final class UserInterceptor implements HandlerInterceptor {
public static class ACCEPTED_URLS_NO_CODE {
public static final String ROOT = "/";
public static final String SET_EFFECTIVE_CODE = "/set-effective-code/";
public static final String ERROR = "/error/";
public static boolean accept(String path) {
return ( ROOT.equals(path) || SET_EFFECTIVE_CODE.equals(path) || ERROR.equals(path) );
}
}
private static final Logger LOGGER = LoggerFactory.getLogger(UserInterceptor.class);
private static final char PROXY_PRINCIPAL_DELIMITER = ',';
@Value("${principal.proxy}")
private boolean proxyPrincipal;
@Autowired
private AuthorizationService authorizationService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
Principal p = request.getUserPrincipal();
if (p == null) {
LOGGER.error("Principal is missing!");
throw new Exception("Principal is missing!");
}
String userName = p.getName();
if (proxyPrincipal) {
int index = userName.indexOf(PROXY_PRINCIPAL_DELIMITER) + 1;
userName = userName.substring(index, userName.indexOf(PROXY_PRINCIPAL_DELIMITER, index));
}
UserVO userData = (UserVO) session.getAttribute("currentUser");
if (userData == null || !userData.getUserName().equals(userName)) {
userData = authorizationService.getUser(userName);
session.setAttribute("currentUser", userData);
}
if (userData.getTravellerCode() == null) {
String selectedCode = "T1";
if (selectedCode != null) {
userData.selectTravellerCode(selectedCode);
} else if (!ACCEPTED_URLS_NO_CODE.accept(request.getServletPath()) ) {
response.addHeader(HttpHeaders.LOCATION, request.getContextPath() + ACCEPTED_URLS_NO_CODE.ROOT);
response.setStatus(HttpServletResponse.SC_FOUND);
return false;
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
How to configure simple spring security
Below are the steps to configure spring security in an web application
1. Add user & roles in the application/web server in case of JBOSS user and roles can be created in C:\JBOSS\jboss-eap-6.4\bin\add-user.bat
2. Add below dependency in pom
<spring.security.version>4.0.1.RELEASE</spring.security.version>
<!-- Spring security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<scope>compile</scope>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<scope>compile</scope>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${spring.security.version}</version>
</dependency>
3. Add the below ones in dispatcher-servlet.xml
<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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
..
…
<security:http auto-config="false" entry-point-ref="preAuthenticatedProcessingFilterEntryPoint">
<security:custom-filter position="PRE_AUTH_FILTER" ref="j2eePreAuthFilter" />
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref='preAuthenticatedAuthenticationProvider' />
</security:authentication-manager>
<bean id="preAuthenticatedAuthenticationProvider"
class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService" />
</bean>
<bean id="preAuthenticatedUserDetailsService"
class="org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService" />
<bean id="j2eePreAuthFilter"
class="org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationDetailsSource">
<bean
class="org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource">
<property name="mappableRolesRetriever">
<bean
class="org.springframework.security.web.authentication.preauth.j2ee.WebXmlMappableAttributesRetriever" />
</property>
<property name="userRoles2GrantedAuthoritiesMapper">
<bean
class="org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper">
<property name="convertAttributeToUpperCase" value="false" />
<property name="attributePrefix" value=""/>
</bean>
</property>
</bean>
</property>
</bean>
<bean id="preAuthenticatedProcessingFilterEntryPoint"
class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
<bean id="httpRequestAccessDecisionManager"
class="org.springframework.security.access.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false" />
<!-- <property name="decisionVoters">
<list>
<ref bean="roleVoter" />
</list>
</property> -->
<constructor-arg ref="roleVoter"/>
</bean>
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter" />
<bean id="securityContextHolderAwareRequestFilter"
class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter" />
<!--end Spring-Security -->
4. Add below ones in web.xml , have appropriate role names pertaining to the project.
<security-constraint>
<display-name>welcome</display-name>
<web-resource-collection>
<web-resource-name>welcome</web-resource-name>
<description/>
<url-pattern>/welcome</url-pattern>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>traveller</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description/>
<role-name>traveller</role-name>
</security-role>
<security-constraint>
<display-name>status</display-name>
<web-resource-collection>
<web-resource-name>status</web-resource-name>
<description/>
<url-pattern>/welcome</url-pattern>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>traveller-status</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description/>
<role-name>traveller-status</role-name>
</security-role>
<security-constraint>
<display-name>desk</display-name>
<web-resource-collection>
<web-resource-name>desk</web-resource-name>
<description/>
<url-pattern>/status</url-pattern>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>traveller-desk</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description/>
<role-name>traveller-desk</role-name>
</security-role>
1. Add user & roles in the application/web server in case of JBOSS user and roles can be created in C:\JBOSS\jboss-eap-6.4\bin\add-user.bat
2. Add below dependency in pom
<spring.security.version>4.0.1.RELEASE</spring.security.version>
<!-- Spring security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<scope>compile</scope>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<scope>compile</scope>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${spring.security.version}</version>
</dependency>
3. Add the below ones in dispatcher-servlet.xml
<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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
..
…
<security:http auto-config="false" entry-point-ref="preAuthenticatedProcessingFilterEntryPoint">
<security:custom-filter position="PRE_AUTH_FILTER" ref="j2eePreAuthFilter" />
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref='preAuthenticatedAuthenticationProvider' />
</security:authentication-manager>
<bean id="preAuthenticatedAuthenticationProvider"
class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService" />
</bean>
<bean id="preAuthenticatedUserDetailsService"
class="org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService" />
<bean id="j2eePreAuthFilter"
class="org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationDetailsSource">
<bean
class="org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource">
<property name="mappableRolesRetriever">
<bean
class="org.springframework.security.web.authentication.preauth.j2ee.WebXmlMappableAttributesRetriever" />
</property>
<property name="userRoles2GrantedAuthoritiesMapper">
<bean
class="org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper">
<property name="convertAttributeToUpperCase" value="false" />
<property name="attributePrefix" value=""/>
</bean>
</property>
</bean>
</property>
</bean>
<bean id="preAuthenticatedProcessingFilterEntryPoint"
class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
<bean id="httpRequestAccessDecisionManager"
class="org.springframework.security.access.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false" />
<!-- <property name="decisionVoters">
<list>
<ref bean="roleVoter" />
</list>
</property> -->
<constructor-arg ref="roleVoter"/>
</bean>
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter" />
<bean id="securityContextHolderAwareRequestFilter"
class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter" />
<!--end Spring-Security -->
4. Add below ones in web.xml , have appropriate role names pertaining to the project.
<security-constraint>
<display-name>welcome</display-name>
<web-resource-collection>
<web-resource-name>welcome</web-resource-name>
<description/>
<url-pattern>/welcome</url-pattern>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>traveller</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description/>
<role-name>traveller</role-name>
</security-role>
<security-constraint>
<display-name>status</display-name>
<web-resource-collection>
<web-resource-name>status</web-resource-name>
<description/>
<url-pattern>/welcome</url-pattern>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>traveller-status</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description/>
<role-name>traveller-status</role-name>
</security-role>
<security-constraint>
<display-name>desk</display-name>
<web-resource-collection>
<web-resource-name>desk</web-resource-name>
<description/>
<url-pattern>/status</url-pattern>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>traveller-desk</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description/>
<role-name>traveller-desk</role-name>
</security-role>
How to write Spring Batch
Create a xml such as scheduler-batch-job-context.xml with the content as like 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:batch="http://www.springframework.org/schema/batch"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<batch:job id="schedulerJob">
<batch:step id="scheduleStep">
<batch:tasklet transaction-manager="jobTransactionManager" >
<batch:chunk
reader="schedulerReader"
processor="schedulerProcessor"
writer="schedulerWriter"
commit-interval="#{jobParameters['commit.interval']}">
</batch:chunk>
<batch:listeners>
<batch:listener ref="errorListener" />
</batch:listeners>
</batch:tasklet>
</batch:step>
</batch:job>
<!-- *** READING *** -->
<bean id="schedulerReader"
class="com.reader.SchedulerReader"
init-method="init"
scope="step">
<property name="service" ref="service" />
</bean>
<!-- *** PROCESSING *** -->
<bean id="schedulerProcessor"
class="com.processor.SchedulerProcessor"
scope="step"/>
<!-- *** WRITING *** -->
<bean id="schedulerWriter"
class="org.springframework.batch.item.support.CompositeItemWriter">
<property name="delegates">
<list>
<ref bean="schedulerLogWriter"/>
<ref bean="schedulerUpdateWriter"/>
</list>
</property>
</bean>
<bean id="schedulerLogWriter"
class="org.springframework.batch.item.adapter.ItemWriterAdapter"
scope="step">
<property name="targetObject" ref="service" />
<property name="targetMethod" value="logChange" />
</bean>
<bean id="schedulerUpdateWriter"
class="org.springframework.batch.item.adapter.ItemWriterAdapter"
scope="step">
<property name="targetObject" ref="service" />
<property name="targetMethod" value="updateSchedulerStatus" />
</bean>
</beans>
Create an xml such as application-context.xml with the content as 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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:property-placeholder ignore-unresolvable="true"
location="file:///${batch.home}/card-support-batches.properties" />
<context:component-scan base-package="com" />
<bean id="jobDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${batch.data.database.driverClassName}" />
<property name="url" value="${batch.data.database.url}" />
<property name="username" value="${batch.data.database.username}" />
<property name="password" value="${batch.data.database.password}" />
</bean>
<bean id="jobTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="jobDataSource"/>
</bean>
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="jobDataSource" />
</bean>
</beans>
Create an xml such as validator-batch-job-context.xml with the content as 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:batch="http://www.springframework.org/schema/batch"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-3.0.xsd">
<batch:job id="validatorJob">
<batch:step id="validateValue">
<batch:tasklet transaction-manager="jobTransactionManager" start-limit="10" >
<batch:chunk
reader="validatorReader"
processor="validateProcessor"
writer="compositeWriter"
commit-interval="#{jobParameters['commit.interval']}">
</batch:chunk>
<batch:listeners>
<batch:listener ref="errorListener" />
</batch:listeners>
</batch:tasklet>
</batch:step>
</batch:job>
<!-- *** READING *** -->
<bean id="validatorReader"
class="com.reader.validatorReader"
init-method="init"
scope="step">
<property name="service" ref="service" />
</bean>
<!-- *** PROCESSING *** -->
<bean id="validateProcessor"
class="com.processor.validatorProcessor"
scope="step"/>
<!-- *** WRITING *** -->
<bean id="compositeWriter"
class="org.springframework.batch.item.support.CompositeItemWriter">
<property name="delegates">
<list>
<ref bean="validatorLogWriter"/>
</list>
</property>
</bean>
<bean id="validatorLogWriter"
class="org.springframework.batch.item.adapter.ItemWriterAdapter"
scope="step">
<property name="targetObject" ref="service" />
<property name="targetMethod" value="logChange" />
</bean>
<!--
<bean id="validatorUpdateWriter"
class="org.springframework.batch.item.adapter.ItemWriterAdapter"
scope="step">
<property name="targetObject" ref="service" />
<property name="targetMethod" value="logChange" />
</bean>
-->
</beans>
create a xml such as launch-context.xml with the content as like 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:batch="http://www.springframework.org/schema/batch"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean class="org.springframework.batch.core.scope.StepScope">
<property name="proxyTargetClass" value="true"/>
</bean>
<bean id="jobControlDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${batch.control.database.driverClassName}" />
<property name="url" value="${batch.control.database.url}" />
<property name="username" value="${batch.control.database.username}" />
<property name="password" value="${batch.control.database.password}" />
</bean>
<bean id="jobControlTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="jobControlDataSource"/>
</bean>
<batch:job-repository id="jobRepository"
data-source="jobControlDataSource"
transaction-manager="jobControlTransactionManager"
isolation-level-for-create="DEFAULT" />
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
</beans>
Create a error-listener class as like below
---------------
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.listener.ItemListenerSupport;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope(value="step")
public class ErrorListener extends ItemListenerSupport<Object, Object> {
private static final Logger LOGGER = LoggerFactory.getLogger(ErrorListener.class);
public void onReadError(Exception ex) {
LOGGER.error("Encountered error on read", ex);
}
public void onWriteError(Exception ex, Object item) {
LOGGER.error("Encountered error on write", ex);
}
}
Create a java main class which in turn invokes the xml files and launches the scheduler job
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Properties;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class JobRunnerScheduler {
public static void main(String... args) {
/*
if(args.length != 1) {
System.out.println("Enter input parameter - source filename without path.");
System.exit(1);
}
*/
ApplicationContext context = null;
Job job = null;
//String sourceFileName = args[0];
context = new ClassPathXmlApplicationContext(
"classpath*:META-INF/spring/applicationContext.xml",
"classpath:META-INF/spring/batch/launch-context.xml",
"classpath:META-INF/spring/batch/scheduler-batch-job-context.xml");
((AbstractApplicationContext)context).registerShutdownHook();
job = (Job) context.getBean("schedulerJob");
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
JobParameters jobParams = createJobParameters(null);
JobExecution jobExec = null;
try {
jobExec = jobLauncher.run(job, jobParams);
} catch (JobExecutionAlreadyRunningException e) {
e.printStackTrace();
} catch (JobRestartException e) {
e.printStackTrace();
} catch (JobInstanceAlreadyCompleteException e) {
e.printStackTrace();
} catch (JobParametersInvalidException e) {
e.printStackTrace();
}
if ( (jobExec.getExitStatus().getExitCode().equals(ExitStatus.COMPLETED.getExitCode()))
|| (jobExec.getExitStatus().getExitCode().equals(ExitStatus.NOOP.getExitCode())) ) {
System.exit(0);
} else {
System.exit(2);
}
}
private static JobParameters createJobParameters(String sourceFile) {
String commitInterval = null;
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream(System.getProperty("batch.home")
+ "/batches.properties");
prop.load(input);
commitInterval = prop.getProperty("jobParam.commit.interval");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return new JobParametersBuilder()
.addString("commit.interval", commitInterval) //number of rows processed before commit
.addDate("sysdate", new Date()) //variable parameter to allow repeated processing
.toJobParameters();
}
}
Create a processor class as like below
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import com.dto.Dto;
import com.dto.WriterDto;
import com.service.Service;
public class SchedulerProcessor implements ItemProcessor<Dto, WriterDto> {
private static final Logger LOGGER = LoggerFactory.getLogger(SchedulerProcessor.class);
@Autowired
private Service service;
@Override
public WriterDto process(Dto dto) throws Exception {
LOGGER.debug("Processing scheduler " + dto.getId()
");
WriterDto writerDto = null;
try {
writerDto = service.enableOrDisable(dto);
} catch (Exception ex) {
LOGGER.error("SchedulerProcessor error", ex);
throw ex;
}
return writerDto;
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import com.dto.Dto;
import com.dto.WriterDto;
import com.service.Service;
public class Processor implements ItemProcessor<Dto, Dto> {
private static final Logger LOGGER = LoggerFactory.getLogger(Processor.class);
@Autowired
private Service service;
@Override
public Dto process(Dto dto) throws Exception {
LOGGER.debug("Processing update from TIM " + dto.getId()
");
try {
return service.updateOrigValuesFromTim(dto);
} catch (Exception ex) {
LOGGER.error("Processor error", ex);
throw ex;
}
}
}
Create a validator processor class as like below
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import com.dto.Dto;
import com.dto.WriterDto;
import com.service.Service;
public class ValidatorProcessor implements ItemProcessor<Dto, WriterDto> {
private static final Logger LOGGER = LoggerFactory.getLogger(ValidatorProcessor.class);
@Autowired
private Service service;
@Override
public WriterDto process(Dto dto) throws Exception {
LOGGER.debug("Processing scheduler " + dto.getId()
");
WriterDto writerDto = null;
try {
writerDto = service.validateValue(dto);
} catch (Exception ex) {
LOGGER.error("ValidatorProcessor error", ex);
throw ex;
}
return writerDto;
}
}
Create a reader class as like below
import java.util.List;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import com.dto.Dto;
import com.service.Service;
public class SchedulerReader implements ItemReader<Dto> {
List<Dto> items;
private Service Service;
public void init() throws Exception {
items = Service.getsForScheduler();
}
@Override
public Dto read()
throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
if (!items.isEmpty()) {
return items.remove(0);
}
return null;
}
public Service getService() {
return Service;
}
public void setService(Service Service) {
this.Service = Service;
}
}
<?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:batch="http://www.springframework.org/schema/batch"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<batch:job id="schedulerJob">
<batch:step id="scheduleStep">
<batch:tasklet transaction-manager="jobTransactionManager" >
<batch:chunk
reader="schedulerReader"
processor="schedulerProcessor"
writer="schedulerWriter"
commit-interval="#{jobParameters['commit.interval']}">
</batch:chunk>
<batch:listeners>
<batch:listener ref="errorListener" />
</batch:listeners>
</batch:tasklet>
</batch:step>
</batch:job>
<!-- *** READING *** -->
<bean id="schedulerReader"
class="com.reader.SchedulerReader"
init-method="init"
scope="step">
<property name="service" ref="service" />
</bean>
<!-- *** PROCESSING *** -->
<bean id="schedulerProcessor"
class="com.processor.SchedulerProcessor"
scope="step"/>
<!-- *** WRITING *** -->
<bean id="schedulerWriter"
class="org.springframework.batch.item.support.CompositeItemWriter">
<property name="delegates">
<list>
<ref bean="schedulerLogWriter"/>
<ref bean="schedulerUpdateWriter"/>
</list>
</property>
</bean>
<bean id="schedulerLogWriter"
class="org.springframework.batch.item.adapter.ItemWriterAdapter"
scope="step">
<property name="targetObject" ref="service" />
<property name="targetMethod" value="logChange" />
</bean>
<bean id="schedulerUpdateWriter"
class="org.springframework.batch.item.adapter.ItemWriterAdapter"
scope="step">
<property name="targetObject" ref="service" />
<property name="targetMethod" value="updateSchedulerStatus" />
</bean>
</beans>
Create an xml such as application-context.xml with the content as 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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:property-placeholder ignore-unresolvable="true"
location="file:///${batch.home}/card-support-batches.properties" />
<context:component-scan base-package="com" />
<bean id="jobDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${batch.data.database.driverClassName}" />
<property name="url" value="${batch.data.database.url}" />
<property name="username" value="${batch.data.database.username}" />
<property name="password" value="${batch.data.database.password}" />
</bean>
<bean id="jobTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="jobDataSource"/>
</bean>
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="jobDataSource" />
</bean>
</beans>
Create an xml such as validator-batch-job-context.xml with the content as 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:batch="http://www.springframework.org/schema/batch"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-3.0.xsd">
<batch:job id="validatorJob">
<batch:step id="validateValue">
<batch:tasklet transaction-manager="jobTransactionManager" start-limit="10" >
<batch:chunk
reader="validatorReader"
processor="validateProcessor"
writer="compositeWriter"
commit-interval="#{jobParameters['commit.interval']}">
</batch:chunk>
<batch:listeners>
<batch:listener ref="errorListener" />
</batch:listeners>
</batch:tasklet>
</batch:step>
</batch:job>
<!-- *** READING *** -->
<bean id="validatorReader"
class="com.reader.validatorReader"
init-method="init"
scope="step">
<property name="service" ref="service" />
</bean>
<!-- *** PROCESSING *** -->
<bean id="validateProcessor"
class="com.processor.validatorProcessor"
scope="step"/>
<!-- *** WRITING *** -->
<bean id="compositeWriter"
class="org.springframework.batch.item.support.CompositeItemWriter">
<property name="delegates">
<list>
<ref bean="validatorLogWriter"/>
</list>
</property>
</bean>
<bean id="validatorLogWriter"
class="org.springframework.batch.item.adapter.ItemWriterAdapter"
scope="step">
<property name="targetObject" ref="service" />
<property name="targetMethod" value="logChange" />
</bean>
<!--
<bean id="validatorUpdateWriter"
class="org.springframework.batch.item.adapter.ItemWriterAdapter"
scope="step">
<property name="targetObject" ref="service" />
<property name="targetMethod" value="logChange" />
</bean>
-->
</beans>
create a xml such as launch-context.xml with the content as like 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:batch="http://www.springframework.org/schema/batch"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean class="org.springframework.batch.core.scope.StepScope">
<property name="proxyTargetClass" value="true"/>
</bean>
<bean id="jobControlDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${batch.control.database.driverClassName}" />
<property name="url" value="${batch.control.database.url}" />
<property name="username" value="${batch.control.database.username}" />
<property name="password" value="${batch.control.database.password}" />
</bean>
<bean id="jobControlTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="jobControlDataSource"/>
</bean>
<batch:job-repository id="jobRepository"
data-source="jobControlDataSource"
transaction-manager="jobControlTransactionManager"
isolation-level-for-create="DEFAULT" />
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
</beans>
Create a error-listener class as like below
---------------
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.listener.ItemListenerSupport;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope(value="step")
public class ErrorListener extends ItemListenerSupport<Object, Object> {
private static final Logger LOGGER = LoggerFactory.getLogger(ErrorListener.class);
public void onReadError(Exception ex) {
LOGGER.error("Encountered error on read", ex);
}
public void onWriteError(Exception ex, Object item) {
LOGGER.error("Encountered error on write", ex);
}
}
Create a java main class which in turn invokes the xml files and launches the scheduler job
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Properties;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class JobRunnerScheduler {
public static void main(String... args) {
/*
if(args.length != 1) {
System.out.println("Enter input parameter - source filename without path.");
System.exit(1);
}
*/
ApplicationContext context = null;
Job job = null;
//String sourceFileName = args[0];
context = new ClassPathXmlApplicationContext(
"classpath*:META-INF/spring/applicationContext.xml",
"classpath:META-INF/spring/batch/launch-context.xml",
"classpath:META-INF/spring/batch/scheduler-batch-job-context.xml");
((AbstractApplicationContext)context).registerShutdownHook();
job = (Job) context.getBean("schedulerJob");
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
JobParameters jobParams = createJobParameters(null);
JobExecution jobExec = null;
try {
jobExec = jobLauncher.run(job, jobParams);
} catch (JobExecutionAlreadyRunningException e) {
e.printStackTrace();
} catch (JobRestartException e) {
e.printStackTrace();
} catch (JobInstanceAlreadyCompleteException e) {
e.printStackTrace();
} catch (JobParametersInvalidException e) {
e.printStackTrace();
}
if ( (jobExec.getExitStatus().getExitCode().equals(ExitStatus.COMPLETED.getExitCode()))
|| (jobExec.getExitStatus().getExitCode().equals(ExitStatus.NOOP.getExitCode())) ) {
System.exit(0);
} else {
System.exit(2);
}
}
private static JobParameters createJobParameters(String sourceFile) {
String commitInterval = null;
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream(System.getProperty("batch.home")
+ "/batches.properties");
prop.load(input);
commitInterval = prop.getProperty("jobParam.commit.interval");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return new JobParametersBuilder()
.addString("commit.interval", commitInterval) //number of rows processed before commit
.addDate("sysdate", new Date()) //variable parameter to allow repeated processing
.toJobParameters();
}
}
Create a processor class as like below
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import com.dto.Dto;
import com.dto.WriterDto;
import com.service.Service;
public class SchedulerProcessor implements ItemProcessor<Dto, WriterDto> {
private static final Logger LOGGER = LoggerFactory.getLogger(SchedulerProcessor.class);
@Autowired
private Service service;
@Override
public WriterDto process(Dto dto) throws Exception {
LOGGER.debug("Processing scheduler " + dto.getId()
");
WriterDto writerDto = null;
try {
writerDto = service.enableOrDisable(dto);
} catch (Exception ex) {
LOGGER.error("SchedulerProcessor error", ex);
throw ex;
}
return writerDto;
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import com.dto.Dto;
import com.dto.WriterDto;
import com.service.Service;
public class Processor implements ItemProcessor<Dto, Dto> {
private static final Logger LOGGER = LoggerFactory.getLogger(Processor.class);
@Autowired
private Service service;
@Override
public Dto process(Dto dto) throws Exception {
LOGGER.debug("Processing update from TIM " + dto.getId()
");
try {
return service.updateOrigValuesFromTim(dto);
} catch (Exception ex) {
LOGGER.error("Processor error", ex);
throw ex;
}
}
}
Create a validator processor class as like below
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import com.dto.Dto;
import com.dto.WriterDto;
import com.service.Service;
public class ValidatorProcessor implements ItemProcessor<Dto, WriterDto> {
private static final Logger LOGGER = LoggerFactory.getLogger(ValidatorProcessor.class);
@Autowired
private Service service;
@Override
public WriterDto process(Dto dto) throws Exception {
LOGGER.debug("Processing scheduler " + dto.getId()
");
WriterDto writerDto = null;
try {
writerDto = service.validateValue(dto);
} catch (Exception ex) {
LOGGER.error("ValidatorProcessor error", ex);
throw ex;
}
return writerDto;
}
}
Create a reader class as like below
import java.util.List;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import com.dto.Dto;
import com.service.Service;
public class SchedulerReader implements ItemReader<Dto> {
List<Dto> items;
private Service Service;
public void init() throws Exception {
items = Service.getsForScheduler();
}
@Override
public Dto read()
throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
if (!items.isEmpty()) {
return items.remove(0);
}
return null;
}
public Service getService() {
return Service;
}
public void setService(Service Service) {
this.Service = Service;
}
}
Thursday, 9 March 2017
How to change string number to desired number decimal format
Below code helps to change the string number to desired number decimal format
String str="00000180000000";
BigDecimal number = new BigDecimal(str).divide(new BigDecimal("100"));// assign correct value
BigDecimal number = new BigDecimal(str).divide(new BigDecimal("100"));// assign correct value
NumberFormat nf = NumberFormat.getCurrencyInstance(LocaleContextHolder.getLocale());
DecimalFormatSymbols decimalFormatSymbols = ((DecimalFormat) nf).getDecimalFormatSymbols();
decimalFormatSymbols.setCurrencySymbol("");
((DecimalFormat) nf).setDecimalFormatSymbols(decimalFormatSymbols);
DecimalFormatSymbols decimalFormatSymbols = ((DecimalFormat) nf).getDecimalFormatSymbols();
decimalFormatSymbols.setCurrencySymbol("");
((DecimalFormat) nf).setDecimalFormatSymbols(decimalFormatSymbols);
String formatedNumber = nf.format(number);
Result :
1,800,000.00
Sunday, 8 January 2017
How to write Integration test cases in Spock
Below code helps to find wite spock based test case
import org.springframework.beans.factory.annotation.Autowired;
import spock.lang.Specification
@ContextConfiguration(['classpath*:META-INF/spring/applicationContext.xml'])
@Transactional
class TravelDetailDaoSpec extends Specification {
@Autowired
private TravelDetailDao travelDetailDao;
def "store TravelDetail into db"() {
given:
TravelDetailVO TravelDetailVO =new TravelDetailVO();
TravelDetailVO.setId("C001");
TravelDetailVO.setPlace("vancouver");
TravelDetailVO.setCountry("canada");
when:
travelDetailDao.create(TravelDetailVO);
List<TravelDetailVO> list=travelDetailDao.getDetails("C001");
then:
assertTrue ("Saved Successfully",list.size()>0);
}
import org.springframework.beans.factory.annotation.Autowired;
import spock.lang.Specification
@ContextConfiguration(['classpath*:META-INF/spring/applicationContext.xml'])
@Transactional
class TravelDetailDaoSpec extends Specification {
@Autowired
private TravelDetailDao travelDetailDao;
def "store TravelDetail into db"() {
given:
TravelDetailVO TravelDetailVO =new TravelDetailVO();
TravelDetailVO.setId("C001");
TravelDetailVO.setPlace("vancouver");
TravelDetailVO.setCountry("canada");
when:
travelDetailDao.create(TravelDetailVO);
List<TravelDetailVO> list=travelDetailDao.getDetails("C001");
then:
assertTrue ("Saved Successfully",list.size()>0);
}
Subscribe to:
Posts (Atom)