'분류 전체보기'에 해당되는 글 2491건
- 2016.09.21 windows docker down
- 2016.09.21 409 Conflict
- 2016.09.19 EPSG:4326 to EPSG:900913
- 2016.09.09 jboss-web.xml
- 2016.09.08 jboss get 방식 한글 깨질때 1
- 2016.09.08 대용량 txt 데이터 database 넣기 간략 데몬
- 2016.09.08 Comments Helpful Follow How to configure jboss-deployment-structure.xml in EAR files to force Weld to use JSF Version 1.2?
- 2016.09.08 spring boot 기반 restful 방식 개발시 jsp 컴파일 안되는 문제
- 2016.09.06 Spring 4 MVC ContentNegotiatingViewResolver example
- 2016.08.23 @PropertySource 값이 null 로 들어오는 경우
- 2016.08.23 mybatis query parameter binding
- 2016.08.23 Spring RestTemplate
- 2016.08.23 eclipse Hotswap Agent 1
- 2016.08.17 spring Data access with JDBC
- 2016.08.17 spring boot Common application properties
- 2016.08.17 tibero 암호화, 복호화 샘플
- 2016.08.16 How to convert image into base64 string using javascript
- 2016.08.12 jquery href get post
- 2016.08.11 java excel download poi 대용량 처리
- 2016.08.11 두 랜카드 라우팅 설정하기
- 2016.08.08 See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
- 2016.08.03 Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar
- 2016.08.03 CentOS Installation fails – “Unable to read package metadata.”
- 2016.08.02 mirror
- 2016.08.01 jboss unable to use inetaddress.getlocalhost() to resolve address
- 2016.08.01 liunx svn service 등록
- 2016.08.01 JBoss EAP2 원도우 서비스 등록사용하기
- 2016.07.27 red hat yum 사용
- 2016.07.14 red hat 계열 방화벽 등록
- 2016.06.27 JBoss EAP2 원도우 서비스 등록사용하기
https://community.hortonworks.com/content/kbentry/3160/update-nifi-flow-on-the-fly-via-api.html
409 Conflict(충돌)
다른 요청이나 서버의 구성과 충돌이 있음을 나타냅니다.
충돌에 대한 정보는 응답되는 데이터의 일부로 반환됩니다. 이 코드는 사용자가 충돌을 해결하고 요구를 재전송할 수 있을 것으로 기대할 수 있는 상황에서만 사용할 수 있습니다. 응답 본문은 사용자가 충돌의 원인을 인지할 수 있도록 충분한 정보를 포함해야 합니다. 이상적으로는 응답 엔터티가 사용자 또는 사용자 에이전트가 문제를 해결할 수 있을 정도의 충분한 정보를 포함할 수 있을 것입니다. 그러나 가능하지 않을 수도 있으며 필수 사항은 아닙니다.
충돌은 PUT 요구에 대한 응답으로 발생할 가능성이 높습니다. 버전 관리를 사용하고 있고 PUT 요구를 하는 엔터티가 이전 요구(제 3 자)가 작성한 요구와 충돌되는 자원에 대한 변경 사항을 포함하고 있다면 서버는 409 응답을 사용하여 요구를 완료할 수 없음을 표시해야 합니다. 이 경우 응답 엔터티는 응답 Content-Type이 규정한 형식으로 두 버전 사이의 차이점 목록을 포함해야 합니다.
409 Conflict
The 409 (Conflict) status code indicates that the request could not
be completed due to a conflict with the current state of the target
resource. This code is used in situations where the user might be
able to resolve the conflict and resubmit the request. The server
SHOULD generate a payload that includes enough information for a user
to recognize the source of the conflict.
Conflicts are most likely to occur in response to a PUT request. For
example, if versioning were being used and the representation being
PUT included changes to a resource that conflict with those made by
an earlier (third-party) request, the origin server might use a 409
response to indicate that it can't complete the request. In this
case, the response representation would likely contain information
useful for merging the differences based on the revision history.
[전지구 좌표계]
전세계를 한번에 나타내야 할 때 많이 쓰이는 좌표계들입니다.
*WGS84 경위도: GPS가 사용하는 좌표계
EPSG:4326, EPSG:4166 (Korean 1995)
+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs
*Bessel 1841 경위도: 한국과 일본에 잘 맞는 지역타원체를 사용한 좌표계
EPSG:4004, EPSG:4162 (Korean 1985)
+proj=longlat +ellps=bessel +no_defs +towgs84=-115.80,474.99,674.11,1.16,-2.31,-1.63,6.43
*GRS80 경위도: WGS84와 거의 유사
EPSG:4019, EPSG:4737 (Korean 2000)
+proj=longlat +ellps=GRS80 +no_defs
*Google Mercator: 구글지도/빙지도/야후지도/OSM 등 에서 사용중인 좌표계
EPSG:3857(공식), EPSG:900913(통칭)
+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs
var degrees2meters = function(lon,lat) { | |
var x = lon * 20037508.34 / 180; | |
var y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180); | |
y = y * 20037508.34 / 180; | |
return [x, y] | |
} | |
x= -77.035974 | |
y = 38.898717 | |
console.log(degrees2meters(x,y)) | |
1 2 3 4 5 6 | <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.3V2//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_4_0.dtd"> <jboss-web> <context-root allowLinking="true">/</context-root> <symbolic-linking-enabled>true</symbolic-linking-enabled> </jboss-web> | cs |
spring boot 기반 JdbcTemplate
1 2 3 4 5 | spring.datasource.driver-class-name=com.tmax.tibero.jdbc.TbDriver spring.datasource.url=jdbc:tibero:thin:@8.8.8.8.:8629:tibero spring.datasource.username=id spring.datasource.password=pw | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | package com.example; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.sql.PreparedStatement; import java.sql.SQLException; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementSetter; @SpringBootApplication public class DemoApplication { private static JdbcTemplate jdbcTemplate; private static StringBuffer INSERT_TMP_TBL_MEMBER = new StringBuffer(); public DemoApplication(JdbcTemplate _JdbcTemplate) { // TODO Auto-generated constructor stub DemoApplication.jdbcTemplate = _JdbcTemplate; INSERT_TMP_TBL_MEMBER.append("INSERT INTO TMP_TBL_MEMBER (C_NO,C_BIRTH,C_PHONE,C_PHONE2,C_EMAIL,C_NAME) VALUES(?,?,?,?,?,?)"); } public static void main(String[] args) throws IOException{ SpringApplication.run(DemoApplication.class, args); Resource resource = new ClassPathResource("TBL_MEMBER.txt"); BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream(),"euc-kr")); String tmpStr; while ((tmpStr = reader.readLine()) != null) { // C_NO,C_BIRTH,C_PHONE,C_PHONE2,C_EMAIL,C_NAME String[] params = tmpStr.split(","); if(params.length == 6){ INSERT_TB_FILE_MANAGE(params); }else{ System.out.println(params.length+":"+params.toString()); } } } private static void INSERT_TB_FILE_MANAGE(String[] params) { jdbcTemplate.update(INSERT_TMP_TBL_MEMBER.toString(), new PreparedStatementSetter() { @Override public void setValues(PreparedStatement preparedStatement) throws SQLException { // TODO Auto-generated method stub preparedStatement.setString(1, params[0] == null ? "" : params[0]); preparedStatement.setString(2, params[1] == null ? "" : params[1]); preparedStatement.setString(3, params[2] == null ? "" : params[2]); preparedStatement.setString(4, params[3] == null ? "" : params[3]); preparedStatement.setString(5, params[4] == null ? "" : params[4]); preparedStatement.setString(6, params[5] == null ? "" : params[5]); } }); } } | cs |
Issue
- If Weld is not forced to use JSF Version 1.2, it picks the 2.1 Version (despite the declaration of Mojarra-1.2 in web.xml) and the following error occurs:
14:30:27,385 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/CDI_JSF_WebDemo]] (ServerService Thread Pool -- 63) JBWEB000287: Exception sending context initialized event to listener instance of class com.sun.faces.config.ConfigureListener: com.sun.faces.config.ConfigurationException: CONFIGURATION FAILED! org.jboss.as.weld.webtier.jsf.WeldApplicationFactory
at com.sun.faces.config.ConfigManager.initialize(ConfigManager.java:215) [jsf-impl-1.2_15-b01-redhat-3.jar:1.2_15-b01-redhat-3]
at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:200) [jsf-impl-1.2_15-b01-redhat-3.jar:1.2_15-b01-redhat-3]
at org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:3339) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1]
at org.apache.catalina.core.StandardContext.start(StandardContext.java:3777) [jbossweb-7.2.0.Final-redhat-1.jar:7.2.0.Final-redhat-1]
at org.jboss.as.web.deployment.WebDeploymentService.doStart(WebDeploymentService.java:156) [jboss-as-web-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8]
at org.jboss.as.web.deployment.WebDeploymentService.access$000(WebDeploymentService.java:60) [jboss-as-web-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8]
at org.jboss.as.web.deployment.WebDeploymentService$1.run(WebDeploymentService.java:93) [jboss-as-web-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [rt.jar:1.7.0_65]
at java.util.concurrent.FutureTask.run(FutureTask.java:262) [rt.jar:1.7.0_65]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_65]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_65]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_65]
at org.jboss.threads.JBossThread.run(JBossThread.java:122)
Caused by: java.lang.InstantiationException: org.jboss.as.weld.webtier.jsf.WeldApplicationFactory
at java.lang.Class.newInstance(Class.java:359) [rt.jar:1.7.0_65]
at javax.faces.FactoryFinder.getImplGivenPreviousImpl(FactoryFinder.java:537) [jsf-api-1.2_15-b01-redhat-3.jar:1.2_15-b01-redhat-3]
at javax.faces.FactoryFinder.getImplementationInstance(FactoryFinder.java:405) [jsf-api-1.2_15-b01-redhat-3.jar:1.2_15-b01-redhat-3]
at javax.faces.FactoryFinder.access$400(FactoryFinder.java:135) [jsf-api-1.2_15-b01-redhat-3.jar:1.2_15-b01-redhat-3]
at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:717) [jsf-api-1.2_15-b01-redhat-3.jar:1.2_15-b01-redhat-3]
at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:239) [jsf-api-1.2_15-b01-redhat-3.jar:1.2_15-b01-redhat-3]
at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:187) [jsf-impl-1.2_15-b01-redhat-3.jar:1.2_15-b01-redhat-3]
at com.sun.faces.config.processor.FactoryConfigProcessor.process(FactoryConfigProcessor.java:132) [jsf-impl-1.2_15-b01-redhat-3.jar:1.2_15-b01-redhat-3]
at com.sun.faces.config.ConfigManager.initialize(ConfigManager.java:205) [jsf-impl-1.2_15-b01-redhat-3.jar:1.2_15-b01-redhat-3]
... 12 more
14:30:27,388 ERROR [org.apache.catalina.core] (ServerService Thread Pool -- 63) JBWEB001103: Error detected during context /CDI_JSF_WebDemo start, will stop it
14:30:27,395 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 63) MSC000001: Failed to start service jboss.web.deployment.default-host./CDI_JSF_WebDemo: org.jboss.msc.service.StartException in service jboss.web.deployment.default-host./CDI_JSF_WebDemo: org.jboss.msc.service.StartException in anonymous service: JBAS018040: Failed to start context
at org.jboss.as.web.deployment.WebDeploymentService$1.run(WebDeploymentService.java:96)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [rt.jar:1.7.0_65]
at java.util.concurrent.FutureTask.run(FutureTask.java:262) [rt.jar:1.7.0_65]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_65]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_65]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_65]
at org.jboss.threads.JBossThread.run(JBossThread.java:122)
Caused by: org.jboss.msc.service.StartException in anonymous service: JBAS018040: Failed to start context
at org.jboss.as.web.deployment.WebDeploymentService.doStart(WebDeploymentService.java:161)
at org.jboss.as.web.deployment.WebDeploymentService.access$000(WebDeploymentService.java:60)
at org.jboss.as.web.deployment.WebDeploymentService$1.run(WebDeploymentService.java:93)
... 6 more
14:30:27,604 ERROR [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS015870: Deploy of deployment "CDI_JSF_WebDemo.war" was rolled back with the following failure message:
{"JBAS014671: Failed services" => {"jboss.web.deployment.default-host./CDI_JSF_WebDemo" => "org.jboss.msc.service.StartException in service jboss.web.deployment.default-host./CDI_JSF_WebDemo: org.jboss.msc.service.StartException in anonymous service: JBAS018040: Failed to start context
Caused by: org.jboss.msc.service.StartException in anonymous service: JBAS018040: Failed to start context"}}
- If the following Weld modules in JBoss are modified to use JSF Version 1.2, the error does not appear and everything works fine:
"jboss-eap-6.1.0/modules/system/layers/base/org/jboss/as/weld/main/module.xml"
"jboss-eap-6.1.0/modules/system/layers/base/org/jboss/weld/core/main/module.xml"
<dependencies>
...
<module name="javax.faces.api" slot="1.2"/>
...
</dependencies>
- But we get stuck if we try to achieve the same with
"META-INF/jboss-deployment-structure.xml"
. The error appears again:
<jboss-deployment-structure>
<deployment>
<exclusions>
<module name="javax.faces.api"/>
<module name="com.sun.jsf-impl"/>
</exclusions>
<dependencies>
<module name="javax.faces.api" slot="1.2"/>
<module name="com.sun.jsf-impl" slot="1.2"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
- How to use the
"jboss-deployment-structure.xml"
to achieve the same effect as modifying the module dependency definitions? - Is there a "Per Application" solution available, because changing the whole JBoss instance to use JSF 1.2 will cause problems with our JSF 2.0 Applications.
spring boot 기반 restful 방식 개발시 jsp 컴파일 안되는 문제
Deploying a WAR in an Old (Servlet 2.5) Container
Spring Boot uses Servlet 3.0 APIs to initialize the ServletContext
(register Servlets
etc.) so you can’t use the same application out of the box in a Servlet 2.5 container. It is however possible to run a Spring Boot application on an older container with some special tools. If you includeorg.springframework.boot:spring-boot-legacy
as a dependency (maintained separately to the core of Spring Boot and currently available at 1.0.0.RELEASE), all you should need to do is create a web.xml
and declare a context listener to create the application context and your filters and servlets. The context listener is a special purpose one for Spring Boot, but the rest of it is normal for a Spring application in Servlet 2.5. Example:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>demo.Application</param-value> </context-param> <listener> <listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class> </listener> <filter> <filter-name>metricFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>metricFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextAttribute</param-name> <param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
In this example we are using a single application context (the one created by the context listener) and attaching it to the DispatcherServlet
using an init parameter. This is normal in a Spring Boot application (you normally only have one application context).
Spring 4 MVC ContentNegotiatingViewResolver example
This article demonstrates supporting multiple output formats for your Spring 4 MVC application using Spring’s ContentNegotiatingViewResolver. We will be generating application output in XML, JSON, PDF, XLS and HTML format, all using Annotation based configuration.
ContentNegotiatingViewResolver
is an implementation of ViewResolver
, which uses the requested media type (based on filetype extension, URL parameter specifying type of output format or accept header) to select a suitable View for a request. ContentNegotiatingViewResolver does not resolve view by itself but delegates to other ViewResolver you can configure to handle specific views(XML,JSON,PDF,XLS,HTML,..).
Other interesting posts you may like
- Secure Spring REST API using OAuth2
- AngularJS+Spring Security using Basic Authentication
- Secure Spring REST API using Basic Authentication
- Spring 4 MVC+JPA2+Hibernate Many-to-many Example
- Spring 4 Caching Annotations Tutorial
- Spring 4 Cache Tutorial with EhCache
- Spring 4 Email Template Library Example
- Spring 4 Email With Attachment Tutorial
- Spring 4 Email Integration Tutorial
- Spring MVC 4+JMS+ActiveMQ Integration Example
- Spring 4+JMS+ActiveMQ @JmsLister @EnableJms Example
- Spring 4+JMS+ActiveMQ Integration Example
- Spring MVC 4+Apache Tiles 3 Integration Example
- Spring MVC 4+Spring Security 4 + Hibernate Integration Example
- Spring MVC 4+AngularJS Example
- Spring MVC 4+AngularJS Routing with ngRoute Example
- Spring MVC 4+AngularJS Routing with UI-Router Example
- Spring MVC 4+Hibernate 4+MySQL+Maven integration example
- Spring Security 4 Custom Login Form Annotation+XML Example
- Spring Security 4 Hello World Annotation+XML Example
- Hibernate MySQL Maven Hello World Example (Annotation)
- TestNG Hello World Example
- JAXB2 Helloworld Example
- Spring Batch- Read an XML file and write to MySQL Database
Following technologies being used:
- Spring 4.0.6.RELEASE
- jackson-databind 2.4.1.3
- jackson-annotations 2.4.1
- lowagie itext 4.2.1
- Apache POI 3.10-beta2
- Maven 3
- JDK 1.6
- Tomcat 7.0.54
- Eclipse JUNO Service Release 2
Let’s begin.
This article demonstrates supporting multiple output formats for your Spring 4 MVC application using Spring’s ContentNegotiatingViewResolver. We will be generating application output in XML, JSON, PDF, XLS and HTML format, all using Annotation based configuration.
ContentNegotiatingViewResolver
is an implementation of ViewResolver
, which uses the requested media type (based on filetype extension, URL parameter specifying type of output format or accept header) to select a suitable View for a request. ContentNegotiatingViewResolver does not resolve view by itself but delegates to other ViewResolver you can configure to handle specific views(XML,JSON,PDF,XLS,HTML,..).
- Secure Spring REST API using OAuth2
- AngularJS+Spring Security using Basic Authentication
- Secure Spring REST API using Basic Authentication
- Spring 4 MVC+JPA2+Hibernate Many-to-many Example
- Spring 4 Caching Annotations Tutorial
- Spring 4 Cache Tutorial with EhCache
- Spring 4 Email Template Library Example
- Spring 4 Email With Attachment Tutorial
- Spring 4 Email Integration Tutorial
- Spring MVC 4+JMS+ActiveMQ Integration Example
- Spring 4+JMS+ActiveMQ @JmsLister @EnableJms Example
- Spring 4+JMS+ActiveMQ Integration Example
- Spring MVC 4+Apache Tiles 3 Integration Example
- Spring MVC 4+Spring Security 4 + Hibernate Integration Example
- Spring MVC 4+AngularJS Example
- Spring MVC 4+AngularJS Routing with ngRoute Example
- Spring MVC 4+AngularJS Routing with UI-Router Example
- Spring MVC 4+Hibernate 4+MySQL+Maven integration example
- Spring Security 4 Custom Login Form Annotation+XML Example
- Spring Security 4 Hello World Annotation+XML Example
- Hibernate MySQL Maven Hello World Example (Annotation)
- TestNG Hello World Example
- JAXB2 Helloworld Example
- Spring Batch- Read an XML file and write to MySQL Database
Following technologies being used:
- Spring 4.0.6.RELEASE
- jackson-databind 2.4.1.3
- jackson-annotations 2.4.1
- lowagie itext 4.2.1
- Apache POI 3.10-beta2
- Maven 3
- JDK 1.6
- Tomcat 7.0.54
- Eclipse JUNO Service Release 2
Let’s begin.
Step 1: Create the directory structure
Following will be the final directory structure for this example:
We will be using Spring Java Configuration(Annotations). Now let’s add/update the content mentioned in above project structure.
Following will be the final directory structure for this example:
We will be using Spring Java Configuration(Annotations). Now let’s add/update the content mentioned in above project structure.
Step 2: Update pom.xml with required dependencies
<?
xml
version
=
"1.0"
?>
<
project
<
modelVersion
>4.0.0</
modelVersion
>
<
groupId
>com.websystique.springmvc</
groupId
>
<
artifactId
>Spring4MVCContentNegotiatingViewResolverExample</
artifactId
>
<
packaging
>war</
packaging
>
<
version
>1.0.0</
version
>
<
name
>Spring4MVCContentNegotiatingViewResolverExample</
name
>
<
properties
>
<
springframework.version
>4.0.6.RELEASE</
springframework.version
>
</
properties
>
<
dependencies
>
<
dependency
>
<
groupId
>org.springframework</
groupId
>
<
artifactId
>spring-core</
artifactId
>
<
version
>${springframework.version}</
version
>
</
dependency
>
<
dependency
>
<
groupId
>org.springframework</
groupId
>
<
artifactId
>spring-web</
artifactId
>
<
version
>${springframework.version}</
version
>
</
dependency
>
<
dependency
>
<
groupId
>org.springframework</
groupId
>
<
artifactId
>spring-webmvc</
artifactId
>
<
version
>${springframework.version}</
version
>
</
dependency
>
<!-- Needed for XML View (with JAXB2) -->
<
dependency
>
<
groupId
>org.springframework</
groupId
>
<
artifactId
>spring-oxm</
artifactId
>
<
version
>${springframework.version}</
version
>
</
dependency
>
<!-- Needed for JSON View -->
<
dependency
>
<
groupId
>com.fasterxml.jackson.core</
groupId
>
<
artifactId
>jackson-databind</
artifactId
>
<
version
>2.4.1.3</
version
>
</
dependency
>
<
dependency
>
<
groupId
>com.fasterxml.jackson.core</
groupId
>
<
artifactId
>jackson-annotations</
artifactId
>
<
version
>2.4.1</
version
>
</
dependency
>
<!-- Needed for PDF View -->
<
dependency
>
<
groupId
>com.lowagie</
groupId
>
<
artifactId
>itext</
artifactId
>
<
version
>4.2.1</
version
>
</
dependency
>
<!-- Needed for XLS View -->
<
dependency
>
<
groupId
>org.apache.poi</
groupId
>
<
artifactId
>poi</
artifactId
>
<
version
>3.10-beta2</
version
>
</
dependency
>
<!-- Servlet dependencies -->
<
dependency
>
<
groupId
>javax.servlet</
groupId
>
<
artifactId
>javax.servlet-api</
artifactId
>
<
version
>3.1.0</
version
>
</
dependency
>
<
dependency
>
<
groupId
>javax.servlet</
groupId
>
<
artifactId
>jstl</
artifactId
>
<
version
>1.2</
version
>
</
dependency
>
<
dependency
>
<
groupId
>javax.servlet.jsp</
groupId
>
<
artifactId
>javax.servlet.jsp-api</
artifactId
>
<
version
>2.3.1</
version
>
</
dependency
>
</
dependencies
>
<
build
>
<
pluginManagement
>
<
plugins
>
<
plugin
>
<
groupId
>org.apache.maven.plugins</
groupId
>
<
artifactId
>maven-compiler-plugin</
artifactId
>
<
version
>3.2</
version
>
<
configuration
>
<
source
>1.6</
source
>
<
target
>1.6</
target
>
</
configuration
>
</
plugin
>
<
plugin
>
<
groupId
>org.apache.maven.plugins</
groupId
>
<
artifactId
>maven-war-plugin</
artifactId
>
<
version
>2.4</
version
>
<
configuration
>
<
warSourceDirectory
>src/main/webapp</
warSourceDirectory
>
<
warName
>Spring4MVCContentNegotiatingViewResolverExample</
warName
>
<
failOnMissingWebXml
>false</
failOnMissingWebXml
>
</
configuration
>
</
plugin
>
</
plugins
>
</
pluginManagement
>
<
finalName
>Spring4MVCContentNegotiatingViewResolverExample</
finalName
>
</
build
>
</
project
>
spring-oxm
is included to support XML output generation (using JAXB2). jackson-databind
&jackson-annotations
provide JSON output support. itext
provide PDF generation library to support PDF output. Apache POI
will help producing XLS output format.
<? xml version = "1.0" ?> < project < modelVersion >4.0.0</ modelVersion > < groupId >com.websystique.springmvc</ groupId > < artifactId >Spring4MVCContentNegotiatingViewResolverExample</ artifactId > < packaging >war</ packaging > < version >1.0.0</ version > < name >Spring4MVCContentNegotiatingViewResolverExample</ name > < properties > < springframework.version >4.0.6.RELEASE</ springframework.version > </ properties > < dependencies > < dependency > < groupId >org.springframework</ groupId > < artifactId >spring-core</ artifactId > < version >${springframework.version}</ version > </ dependency > < dependency > < groupId >org.springframework</ groupId > < artifactId >spring-web</ artifactId > < version >${springframework.version}</ version > </ dependency > < dependency > < groupId >org.springframework</ groupId > < artifactId >spring-webmvc</ artifactId > < version >${springframework.version}</ version > </ dependency > <!-- Needed for XML View (with JAXB2) --> < dependency > < groupId >org.springframework</ groupId > < artifactId >spring-oxm</ artifactId > < version >${springframework.version}</ version > </ dependency > <!-- Needed for JSON View --> < dependency > < groupId >com.fasterxml.jackson.core</ groupId > < artifactId >jackson-databind</ artifactId > < version >2.4.1.3</ version > </ dependency > < dependency > < groupId >com.fasterxml.jackson.core</ groupId > < artifactId >jackson-annotations</ artifactId > < version >2.4.1</ version > </ dependency > <!-- Needed for PDF View --> < dependency > < groupId >com.lowagie</ groupId > < artifactId >itext</ artifactId > < version >4.2.1</ version > </ dependency > <!-- Needed for XLS View --> < dependency > < groupId >org.apache.poi</ groupId > < artifactId >poi</ artifactId > < version >3.10-beta2</ version > </ dependency > <!-- Servlet dependencies --> < dependency > < groupId >javax.servlet</ groupId > < artifactId >javax.servlet-api</ artifactId > < version >3.1.0</ version > </ dependency > < dependency > < groupId >javax.servlet</ groupId > < artifactId >jstl</ artifactId > < version >1.2</ version > </ dependency > < dependency > < groupId >javax.servlet.jsp</ groupId > < artifactId >javax.servlet.jsp-api</ artifactId > < version >2.3.1</ version > </ dependency > </ dependencies > < build > < pluginManagement > < plugins > < plugin > < groupId >org.apache.maven.plugins</ groupId > < artifactId >maven-compiler-plugin</ artifactId > < version >3.2</ version > < configuration > < source >1.6</ source > < target >1.6</ target > </ configuration > </ plugin > < plugin > < groupId >org.apache.maven.plugins</ groupId > < artifactId >maven-war-plugin</ artifactId > < version >2.4</ version > < configuration > < warSourceDirectory >src/main/webapp</ warSourceDirectory > < warName >Spring4MVCContentNegotiatingViewResolverExample</ warName > < failOnMissingWebXml >false</ failOnMissingWebXml > </ configuration > </ plugin > </ plugins > </ pluginManagement > < finalName >Spring4MVCContentNegotiatingViewResolverExample</ finalName > </ build > </ project > |
spring-oxm
is included to support XML output generation (using JAXB2). jackson-databind
&jackson-annotations
provide JSON output support. itext
provide PDF generation library to support PDF output. Apache POI
will help producing XLS output format.
Step 3: Create Spring Configuration Class
com.websystique.springmvc.configuration.AppConfig
package
com.websystique.springmvc.configuration;
import
java.util.ArrayList;
import
java.util.List;
import
org.springframework.context.annotation.Bean;
import
org.springframework.context.annotation.ComponentScan;
import
org.springframework.context.annotation.Configuration;
import
org.springframework.http.MediaType;
import
org.springframework.oxm.jaxb.Jaxb2Marshaller;
import
org.springframework.web.accept.ContentNegotiationManager;
import
org.springframework.web.servlet.ViewResolver;
import
org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import
org.springframework.web.servlet.config.annotation.EnableWebMvc;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import
org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
import
org.springframework.web.servlet.view.InternalResourceViewResolver;
import
org.springframework.web.servlet.view.JstlView;
import
com.websystique.springmvc.model.Pizza;
import
com.websystique.springmvc.viewresolver.ExcelViewResolver;
import
com.websystique.springmvc.viewresolver.JsonViewResolver;
import
com.websystique.springmvc.viewresolver.Jaxb2MarshallingXmlViewResolver;
import
com.websystique.springmvc.viewresolver.PdfViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan
(basePackages =
"com.websystique.springmvc"
)
public
class
AppConfig
extends
WebMvcConfigurerAdapter {
/*
* Configure ContentNegotiationManager
*/
@Override
public
void
configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.ignoreAcceptHeader(
true
).defaultContentType(
MediaType.TEXT_HTML);
}
/*
* Configure ContentNegotiatingViewResolver
*/
@Bean
public
ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {
ContentNegotiatingViewResolver resolver =
new
ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(manager);
// Define all possible view resolvers
List<ViewResolver> resolvers =
new
ArrayList<ViewResolver>();
resolvers.add(jaxb2MarshallingXmlViewResolver());
resolvers.add(jsonViewResolver());
resolvers.add(jspViewResolver());
resolvers.add(pdfViewResolver());
resolvers.add(excelViewResolver());
resolver.setViewResolvers(resolvers);
return
resolver;
}
/*
* Configure View resolver to provide XML output Uses JAXB2 marshaller to
* marshall/unmarshall POJO's (with JAXB annotations) to XML
*/
@Bean
public
ViewResolver jaxb2MarshallingXmlViewResolver() {
Jaxb2Marshaller marshaller =
new
Jaxb2Marshaller();
marshaller.setClassesToBeBound(Pizza.
class
);
return
new
Jaxb2MarshallingXmlViewResolver(marshaller);
}
/*
* Configure View resolver to provide JSON output using JACKSON library to
* convert object in JSON format.
*/
@Bean
public
ViewResolver jsonViewResolver() {
return
new
JsonViewResolver();
}
/*
* Configure View resolver to provide PDF output using lowagie pdf library to
* generate PDF output for an object content
*/
@Bean
public
ViewResolver pdfViewResolver() {
return
new
PdfViewResolver();
}
/*
* Configure View resolver to provide XLS output using Apache POI library to
* generate XLS output for an object content
*/
@Bean
public
ViewResolver excelViewResolver() {
return
new
ExcelViewResolver();
}
/*
* Configure View resolver to provide HTML output This is the default format
* in absence of any type suffix.
*/
@Bean
public
ViewResolver jspViewResolver() {
InternalResourceViewResolver viewResolver =
new
InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.
class
);
viewResolver.setPrefix(
"/WEB-INF/views/"
);
viewResolver.setSuffix(
".jsp"
);
return
viewResolver;
}
}
Let’s discuss above class in details :
First step is to create the ContentNegotiationManager which is used to determine the requested media types of a request by delegating to a list of ContentNegotiationStrategy instances. By defaultPathExtensionContentNegotiationStrategy
is consulted (which uses the URL extension e.g. .xls, .pdf,.json..) , followed by ParameterContentNegotiationStrategy
(which uses the request parameter ‘format=xls’ e.g.), followed by HeaderContentNegotiationStrategy
(which uses HTTP Accept Headers).
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.ignoreAcceptHeader(true).defaultContentType(
MediaType.TEXT_HTML);
}
In our example, we will be using the URL extension to help determine the media types. Also, we have set the default media type to TEXT_HTML in absence of file extension or when the filetype is unknown, that means JSP view resolver will be used when no [known] URL extension found.
Below is the content of pizza.jsp used by default JSP view resolver
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<
html
>
<
head
>
<
meta
http-equiv
=
"Content-Type"
content
=
"text/html; charset=ISO-8859-1"
>
<
title
>Pizza JSP View</
title
>
</
head
>
<
body
>
<
table
border
=
"1"
>
<
tr
>
<
td
>NAME</
td
>
<
td
>Flavor</
td
>
<
td
>Toppings</
td
>
</
tr
>
<
tr
>
<
td
>${pizza.name}</
td
>
<
td
>${pizza.flavor}</
td
>
<
td
>
<
c:forEach
var
=
"item"
items
=
"${pizza.toppings}"
>
<
c:out
value
=
"${item}"
/>
</
c:forEach
>
</
td
>
</
tr
>
</
table
>
</
body
>
</
html
>
Next step is to configure ContentNegotaionViewResolver itself,
public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(manager);
// Define all possible view resolvers
List<
ViewResolver
> resolvers = new ArrayList<
ViewResolver
>();
resolvers.add(jaxb2MarshallingXmlViewResolver());
resolvers.add(jsonViewResolver());
resolvers.add(jspViewResolver());
resolvers.add(pdfViewResolver());
resolvers.add(excelViewResolver());
resolver.setViewResolvers(resolvers);
return resolver;
}
We need to set the ContentNegotiationManager
which will be injected by Spring, and different resolvers for each possible output format our application might produce.
Finally, we have created different view resolvers for XML, JSON, PDF, XLS and HTML output which we will discuss next.
com.websystique.springmvc.configuration.AppConfig
package com.websystique.springmvc.configuration; import java.util.ArrayList; import java.util.List; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.oxm.jaxb.Jaxb2Marshaller; import org.springframework.web.accept.ContentNegotiationManager; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; import com.websystique.springmvc.model.Pizza; import com.websystique.springmvc.viewresolver.ExcelViewResolver; import com.websystique.springmvc.viewresolver.JsonViewResolver; import com.websystique.springmvc.viewresolver.Jaxb2MarshallingXmlViewResolver; import com.websystique.springmvc.viewresolver.PdfViewResolver; @Configuration @EnableWebMvc @ComponentScan (basePackages = "com.websystique.springmvc" ) public class AppConfig extends WebMvcConfigurerAdapter { /* * Configure ContentNegotiationManager */ @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.ignoreAcceptHeader( true ).defaultContentType( MediaType.TEXT_HTML); } /* * Configure ContentNegotiatingViewResolver */ @Bean public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) { ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver(); resolver.setContentNegotiationManager(manager); // Define all possible view resolvers List<ViewResolver> resolvers = new ArrayList<ViewResolver>(); resolvers.add(jaxb2MarshallingXmlViewResolver()); resolvers.add(jsonViewResolver()); resolvers.add(jspViewResolver()); resolvers.add(pdfViewResolver()); resolvers.add(excelViewResolver()); resolver.setViewResolvers(resolvers); return resolver; } /* * Configure View resolver to provide XML output Uses JAXB2 marshaller to * marshall/unmarshall POJO's (with JAXB annotations) to XML */ @Bean public ViewResolver jaxb2MarshallingXmlViewResolver() { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setClassesToBeBound(Pizza. class ); return new Jaxb2MarshallingXmlViewResolver(marshaller); } /* * Configure View resolver to provide JSON output using JACKSON library to * convert object in JSON format. */ @Bean public ViewResolver jsonViewResolver() { return new JsonViewResolver(); } /* * Configure View resolver to provide PDF output using lowagie pdf library to * generate PDF output for an object content */ @Bean public ViewResolver pdfViewResolver() { return new PdfViewResolver(); } /* * Configure View resolver to provide XLS output using Apache POI library to * generate XLS output for an object content */ @Bean public ViewResolver excelViewResolver() { return new ExcelViewResolver(); } /* * Configure View resolver to provide HTML output This is the default format * in absence of any type suffix. */ @Bean public ViewResolver jspViewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setViewClass(JstlView. class ); viewResolver.setPrefix( "/WEB-INF/views/" ); viewResolver.setSuffix( ".jsp" ); return viewResolver; } } |
Let’s discuss above class in details :
First step is to create the ContentNegotiationManager which is used to determine the requested media types of a request by delegating to a list of ContentNegotiationStrategy instances. By defaultPathExtensionContentNegotiationStrategy
is consulted (which uses the URL extension e.g. .xls, .pdf,.json..) , followed by ParameterContentNegotiationStrategy
(which uses the request parameter ‘format=xls’ e.g.), followed by HeaderContentNegotiationStrategy
(which uses HTTP Accept Headers).
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.ignoreAcceptHeader(true).defaultContentType( MediaType.TEXT_HTML); } |
In our example, we will be using the URL extension to help determine the media types. Also, we have set the default media type to TEXT_HTML in absence of file extension or when the filetype is unknown, that means JSP view resolver will be used when no [known] URL extension found.
Below is the content of pizza.jsp used by default JSP view resolver
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> < html > < head > < meta http-equiv = "Content-Type" content = "text/html; charset=ISO-8859-1" > < title >Pizza JSP View</ title > </ head > < body > < table border = "1" > < tr > < td >NAME</ td > < td >Flavor</ td > < td >Toppings</ td > </ tr > < tr > < td >${pizza.name}</ td > < td >${pizza.flavor}</ td > < td > < c:forEach var = "item" items = "${pizza.toppings}" > < c:out value = "${item}" /> </ c:forEach > </ td > </ tr > </ table > </ body > </ html > |
Next step is to configure ContentNegotaionViewResolver itself,
public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) { ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver(); resolver.setContentNegotiationManager(manager); // Define all possible view resolvers List< ViewResolver > resolvers = new ArrayList< ViewResolver >(); resolvers.add(jaxb2MarshallingXmlViewResolver()); resolvers.add(jsonViewResolver()); resolvers.add(jspViewResolver()); resolvers.add(pdfViewResolver()); resolvers.add(excelViewResolver()); resolver.setViewResolvers(resolvers); return resolver; } |
We need to set the ContentNegotiationManager
which will be injected by Spring, and different resolvers for each possible output format our application might produce.
Finally, we have created different view resolvers for XML, JSON, PDF, XLS and HTML output which we will discuss next.
Step 4: Create Different View Resolvers
Let’s now create tha actual view resolvers itself.
XML View Resolver:
This view resolver relies on JAXB2 Marshalling/unmarshalling to produce XML output. The domain class needs to be annotated with JAXB2 annotations.
com.websystique.springmvc.viewresolver.Jaxb2MarshallingXmlViewResolver
package
com.websystique.springmvc.viewresolver;
import
java.util.Locale;
import
org.springframework.oxm.Marshaller;
import
org.springframework.web.servlet.View;
import
org.springframework.web.servlet.ViewResolver;
import
org.springframework.web.servlet.view.xml.MarshallingView;
public
class
Jaxb2MarshallingXmlViewResolver
implements
ViewResolver {
private
Marshaller marshaller;
public
Jaxb2MarshallingXmlViewResolver(Marshaller marshaller) {
this
.marshaller = marshaller;
}
@Override
public
View resolveViewName(String viewName, Locale locale)
throws
Exception {
MarshallingView view =
new
MarshallingView();
view.setMarshaller(marshaller);
return
view;
}
}
Below is the domain object (annotated with standard XML annotations) for our example:
com.websystique.springmvc.model.Pizza
package
com.websystique.springmvc.model;
import
java.util.ArrayList;
import
java.util.List;
import
javax.xml.bind.annotation.XmlElement;
import
javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
(name =
"pizza"
)
public
class
Pizza {
private
String name;
private
String flavor;
private
List<String> toppings =
new
ArrayList<String>();
public
Pizza(){
}
public
Pizza(String name){
this
.name = name;
this
.flavor =
"spicy"
;
this
.toppings.add(
"Cheese"
);
this
.toppings.add(
"bakon"
);
}
@XmlElement
public
void
setName(String name) {
this
.name = name;
}
public
String getName() {
return
name;
}
@XmlElement
public
void
setFlavor(String flavor) {
this
.flavor = flavor;
}
public
String getFlavor() {
return
flavor;
}
public
List<String> getToppings() {
return
toppings;
}
@XmlElement
public
void
setToppings(List<String> toppings) {
this
.toppings = toppings;
}
}
JSON View Resolver:
This view resolver is using Spring MappingJackson2JsonView
to get the view used to convert POJO to JSON.
com.websystique.springmvc.viewresolver.JsonViewResolver
package
com.websystique.springmvc.viewresolver;
import
java.util.Locale;
import
org.springframework.web.servlet.View;
import
org.springframework.web.servlet.ViewResolver;
import
org.springframework.web.servlet.view.json.MappingJackson2JsonView;
public
class
JsonViewResolver
implements
ViewResolver{
@Override
public
View resolveViewName(String viewName, Locale locale)
throws
Exception {
MappingJackson2JsonView view =
new
MappingJackson2JsonView();
view.setPrettyPrint(
true
);
return
view;
}
}
PDF View Resolver:
This view resolver is using lowagie itext library to actually generate PDF output.Also note that actual view extends from Spring AbstractPdfView
which itself internally uses lowagie itext library.
com.websystique.springmvc.viewresolver.PdfView
package
com.websystique.springmvc.viewresolver;
import
java.awt.Color;
import
java.util.Map;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
import
org.springframework.web.servlet.view.document.AbstractPdfView;
import
com.lowagie.text.Document;
import
com.lowagie.text.Element;
import
com.lowagie.text.pdf.PdfPTable;
import
com.lowagie.text.pdf.PdfWriter;
import
com.websystique.springmvc.model.Pizza;
public
class
PdfView
extends
AbstractPdfView {
@Override
protected
void
buildPdfDocument(Map<String, Object> model,
Document document, PdfWriter writer, HttpServletRequest request,
HttpServletResponse response)
throws
Exception {
Pizza pizza = (Pizza) model.get(
"pizza"
);
PdfPTable table =
new
PdfPTable(
3
);
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
table.getDefaultCell().setVerticalAlignment(Element.ALIGN_MIDDLE);
table.getDefaultCell().setBackgroundColor(Color.lightGray);
table.addCell(
"Name"
);
table.addCell(
"Flavor"
);
table.addCell(
"Toppings"
);
table.addCell(pizza.getName());
table.addCell(pizza.getFlavor());
StringBuffer toppings =
new
StringBuffer(
""
);
for
(String topping : pizza.getToppings()) {
toppings.append(topping);
toppings.append(
" "
);
}
table.addCell(toppings.toString());
document.add(table);
}
}
com.websystique.springmvc.viewresolver.PdfViewResolver
package
com.websystique.springmvc.viewresolver;
import
java.util.Locale;
import
org.springframework.web.servlet.View;
import
org.springframework.web.servlet.ViewResolver;
public
class
PdfViewResolver
implements
ViewResolver{
@Override
public
View resolveViewName(String viewName, Locale locale)
throws
Exception {
PdfView view =
new
PdfView();
return
view;
}
}
XLS View Resolver:
This view resolver is using Apache POI library to actually generate Microsoft XLS output.Also note that actual view extends from Spring AbstractExcelView
which itself internally uses Apache POI library.
com.websystique.springmvc.viewresolver.ExcelView
package
com.websystique.springmvc.viewresolver;
import
java.util.Map;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
import
org.apache.poi.hssf.usermodel.HSSFWorkbook;
import
org.apache.poi.ss.usermodel.Cell;
import
org.apache.poi.ss.usermodel.CellStyle;
import
org.apache.poi.ss.usermodel.IndexedColors;
import
org.apache.poi.ss.usermodel.Row;
import
org.apache.poi.ss.usermodel.Sheet;
import
org.springframework.web.servlet.view.document.AbstractExcelView;
import
com.websystique.springmvc.model.Pizza;
public
class
ExcelView
extends
AbstractExcelView {
@Override
protected
void
buildExcelDocument(Map<String, Object> model,
HSSFWorkbook workbook, HttpServletRequest request,
HttpServletResponse response)
throws
Exception {
Pizza pizza = (Pizza) model.get(
"pizza"
);
Sheet sheet = workbook.createSheet(
"sheet 1"
);
CellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.index);
style.setFillPattern(CellStyle.SOLID_FOREGROUND);
style.setAlignment(CellStyle.ALIGN_CENTER);
Row row =
null
;
Cell cell =
null
;
int
rowCount =
0
;
int
colCount =
0
;
// Create header cells
row = sheet.createRow(rowCount++);
cell = row.createCell(colCount++);
cell.setCellStyle(style);
cell.setCellValue(
"Name"
);
cell = row.createCell(colCount++);
cell.setCellStyle(style);
cell.setCellValue(
"Flavor"
);
cell = row.createCell(colCount++);
cell.setCellStyle(style);
cell.setCellValue(
"Toppings"
);
// Create data cells
row = sheet.createRow(rowCount++);
colCount =
0
;
row.createCell(colCount++).setCellValue(pizza.getName());
row.createCell(colCount++).setCellValue(pizza.getFlavor());
StringBuffer toppings =
new
StringBuffer(
""
);
for
(String topping : pizza.getToppings()) {
toppings.append(topping);
toppings.append(
" "
);
}
row.createCell(colCount++).setCellValue(toppings.toString());
for
(
int
i =
0
; i <
3
; i++)
sheet.autoSizeColumn(i,
true
);
}
}
com.websystique.springmvc.viewresolver.ExcelViewResolver
package
com.websystique.springmvc.viewresolver;
import
java.util.Locale;
import
org.springframework.web.servlet.View;
import
org.springframework.web.servlet.ViewResolver;
public
class
ExcelViewResolver
implements
ViewResolver{
@Override
public
View resolveViewName(String viewName, Locale locale)
throws
Exception {
ExcelView view =
new
ExcelView();
return
view;
}
}
That is all needed for ContentNegotaingViewResolver configuration.
To complete the example and make it runnable, let’s add the missing Spring MVC configuration peaces.
Let’s now create tha actual view resolvers itself.
XML View Resolver:
This view resolver relies on JAXB2 Marshalling/unmarshalling to produce XML output. The domain class needs to be annotated with JAXB2 annotations.
com.websystique.springmvc.viewresolver.Jaxb2MarshallingXmlViewResolver
package com.websystique.springmvc.viewresolver; import java.util.Locale; import org.springframework.oxm.Marshaller; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.view.xml.MarshallingView; public class Jaxb2MarshallingXmlViewResolver implements ViewResolver { private Marshaller marshaller; public Jaxb2MarshallingXmlViewResolver(Marshaller marshaller) { this .marshaller = marshaller; } @Override public View resolveViewName(String viewName, Locale locale) throws Exception { MarshallingView view = new MarshallingView(); view.setMarshaller(marshaller); return view; } } |
Below is the domain object (annotated with standard XML annotations) for our example:
com.websystique.springmvc.model.Pizza
package com.websystique.springmvc.model; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement (name = "pizza" ) public class Pizza { private String name; private String flavor; private List<String> toppings = new ArrayList<String>(); public Pizza(){ } public Pizza(String name){ this .name = name; this .flavor = "spicy" ; this .toppings.add( "Cheese" ); this .toppings.add( "bakon" ); } @XmlElement public void setName(String name) { this .name = name; } public String getName() { return name; } @XmlElement public void setFlavor(String flavor) { this .flavor = flavor; } public String getFlavor() { return flavor; } public List<String> getToppings() { return toppings; } @XmlElement public void setToppings(List<String> toppings) { this .toppings = toppings; } } |
JSON View Resolver:
This view resolver is using Spring MappingJackson2JsonView
to get the view used to convert POJO to JSON.
com.websystique.springmvc.viewresolver.JsonViewResolver
package com.websystique.springmvc.viewresolver; import java.util.Locale; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.view.json.MappingJackson2JsonView; public class JsonViewResolver implements ViewResolver{ @Override public View resolveViewName(String viewName, Locale locale) throws Exception { MappingJackson2JsonView view = new MappingJackson2JsonView(); view.setPrettyPrint( true ); return view; } } |
PDF View Resolver:
This view resolver is using lowagie itext library to actually generate PDF output.Also note that actual view extends from Spring AbstractPdfView
which itself internally uses lowagie itext library.
com.websystique.springmvc.viewresolver.PdfView
package com.websystique.springmvc.viewresolver; import java.awt.Color; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.view.document.AbstractPdfView; import com.lowagie.text.Document; import com.lowagie.text.Element; import com.lowagie.text.pdf.PdfPTable; import com.lowagie.text.pdf.PdfWriter; import com.websystique.springmvc.model.Pizza; public class PdfView extends AbstractPdfView { @Override protected void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer, HttpServletRequest request, HttpServletResponse response) throws Exception { Pizza pizza = (Pizza) model.get( "pizza" ); PdfPTable table = new PdfPTable( 3 ); table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER); table.getDefaultCell().setVerticalAlignment(Element.ALIGN_MIDDLE); table.getDefaultCell().setBackgroundColor(Color.lightGray); table.addCell( "Name" ); table.addCell( "Flavor" ); table.addCell( "Toppings" ); table.addCell(pizza.getName()); table.addCell(pizza.getFlavor()); StringBuffer toppings = new StringBuffer( "" ); for (String topping : pizza.getToppings()) { toppings.append(topping); toppings.append( " " ); } table.addCell(toppings.toString()); document.add(table); } } |
com.websystique.springmvc.viewresolver.PdfViewResolver
package com.websystique.springmvc.viewresolver; import java.util.Locale; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; public class PdfViewResolver implements ViewResolver{ @Override public View resolveViewName(String viewName, Locale locale) throws Exception { PdfView view = new PdfView(); return view; } } |
XLS View Resolver:
This view resolver is using Apache POI library to actually generate Microsoft XLS output.Also note that actual view extends from Spring AbstractExcelView
which itself internally uses Apache POI library.
com.websystique.springmvc.viewresolver.ExcelView
package com.websystique.springmvc.viewresolver; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.springframework.web.servlet.view.document.AbstractExcelView; import com.websystique.springmvc.model.Pizza; public class ExcelView extends AbstractExcelView { @Override protected void buildExcelDocument(Map<String, Object> model, HSSFWorkbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception { Pizza pizza = (Pizza) model.get( "pizza" ); Sheet sheet = workbook.createSheet( "sheet 1" ); CellStyle style = workbook.createCellStyle(); style.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.index); style.setFillPattern(CellStyle.SOLID_FOREGROUND); style.setAlignment(CellStyle.ALIGN_CENTER); Row row = null ; Cell cell = null ; int rowCount = 0 ; int colCount = 0 ; // Create header cells row = sheet.createRow(rowCount++); cell = row.createCell(colCount++); cell.setCellStyle(style); cell.setCellValue( "Name" ); cell = row.createCell(colCount++); cell.setCellStyle(style); cell.setCellValue( "Flavor" ); cell = row.createCell(colCount++); cell.setCellStyle(style); cell.setCellValue( "Toppings" ); // Create data cells row = sheet.createRow(rowCount++); colCount = 0 ; row.createCell(colCount++).setCellValue(pizza.getName()); row.createCell(colCount++).setCellValue(pizza.getFlavor()); StringBuffer toppings = new StringBuffer( "" ); for (String topping : pizza.getToppings()) { toppings.append(topping); toppings.append( " " ); } row.createCell(colCount++).setCellValue(toppings.toString()); for ( int i = 0 ; i < 3 ; i++) sheet.autoSizeColumn(i, true ); } } |
com.websystique.springmvc.viewresolver.ExcelViewResolver
package com.websystique.springmvc.viewresolver; import java.util.Locale; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; public class ExcelViewResolver implements ViewResolver{ @Override public View resolveViewName(String viewName, Locale locale) throws Exception { ExcelView view = new ExcelView(); return view; } } |
That is all needed for ContentNegotaingViewResolver configuration.
To complete the example and make it runnable, let’s add the missing Spring MVC configuration peaces.
Step 5: Create Controller class
Below is a trivial REST based controller for our example.
com.websystique.springmvc.controller.AppController
package
com.websystique.springmvc.controller;
import
org.springframework.stereotype.Controller;
import
org.springframework.ui.ModelMap;
import
org.springframework.web.bind.annotation.PathVariable;
import
org.springframework.web.bind.annotation.RequestMapping;
import
org.springframework.web.bind.annotation.RequestMethod;
import
com.websystique.springmvc.model.Pizza;
@Controller
public
class
AppController {
@RequestMapping
(value=
"/pizzavalley/{pizzaName}"
, method = RequestMethod.GET)
public
String getPizza(
@PathVariable
String pizzaName, ModelMap model) {
Pizza pizza =
new
Pizza(pizzaName);
model.addAttribute(
"pizza"
, pizza);
return
"pizza"
;
}
}
Below is a trivial REST based controller for our example.
com.websystique.springmvc.controller.AppController
package com.websystique.springmvc.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.websystique.springmvc.model.Pizza; @Controller public class AppController { @RequestMapping (value= "/pizzavalley/{pizzaName}" , method = RequestMethod.GET) public String getPizza( @PathVariable String pizzaName, ModelMap model) { Pizza pizza = new Pizza(pizzaName); model.addAttribute( "pizza" , pizza); return "pizza" ; } } |
Step 6: Create Initialization Class
Add an initializer class implementing WebApplicationInitializer
as shown below(which in this case acts as replacement of any spring configuration defined in web.xml). During Servlet 3.0 Container startup, this class will be loaded and instantiated and its onStartup method will be called by servlet container.
com.websystique.springmvc.configuration.AppInitializer
package
com.websystique.springmvc.configuration;
import
javax.servlet.ServletContext;
import
javax.servlet.ServletException;
import
javax.servlet.ServletRegistration;
import
org.springframework.web.WebApplicationInitializer;
import
org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import
org.springframework.web.servlet.DispatcherServlet;
public
class
AppInitializer
implements
WebApplicationInitializer {
public
void
onStartup(ServletContext container)
throws
ServletException {
AnnotationConfigWebApplicationContext ctx =
new
AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.
class
);
ctx.setServletContext(container);
ServletRegistration.Dynamic servlet = container.addServlet(
"dispatcher"
,
new
DispatcherServlet(ctx));
servlet.setLoadOnStartup(
1
);
servlet.addMapping(
"/"
);
}
}
UPDATE: Note that above class can be written even more concisely [and it’s the preferred way], by extending AbstractAnnotationConfigDispatcherServletInitializer
base class, as shown below:
package
com.websystique.springmvc.configuration;
import
org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public
class
AppInitializer
extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected
Class<?>[] getRootConfigClasses() {
return
new
Class[] { AppConfig.
class
};
}
@Override
protected
Class<?>[] getServletConfigClasses() {
return
null
;
}
@Override
protected
String[] getServletMappings() {
return
new
String[] {
"/"
};
}
}
Add an initializer class implementing WebApplicationInitializer
as shown below(which in this case acts as replacement of any spring configuration defined in web.xml). During Servlet 3.0 Container startup, this class will be loaded and instantiated and its onStartup method will be called by servlet container.
com.websystique.springmvc.configuration.AppInitializer
package com.websystique.springmvc.configuration; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; public class AppInitializer implements WebApplicationInitializer { public void onStartup(ServletContext container) throws ServletException { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(AppConfig. class ); ctx.setServletContext(container); ServletRegistration.Dynamic servlet = container.addServlet( "dispatcher" , new DispatcherServlet(ctx)); servlet.setLoadOnStartup( 1 ); servlet.addMapping( "/" ); } } |
UPDATE: Note that above class can be written even more concisely [and it’s the preferred way], by extending AbstractAnnotationConfigDispatcherServletInitializer
base class, as shown below:
package com.websystique.springmvc.configuration; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { AppConfig. class }; } @Override protected Class<?>[] getServletConfigClasses() { return null ; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } } |
Step 7: Build and Deploy the application
Now build the war (via eclipse or maven [ mvn clean install]). Deploy the war to a Servlet 3.0 container. Since here i am using Tomcat, i will simply put this war file into tomcat webapps
folder and click on start.bat
inside tomcat bin directory.
Run it.Below are the snapshot of sample run triggering deffernt outputs (notice URL extensions)
That’s it.
Now build the war (via eclipse or maven [ mvn clean install]). Deploy the war to a Servlet 3.0 container. Since here i am using Tomcat, i will simply put this war file into tomcat webapps
folder and click on start.bat
inside tomcat bin directory.
Run it.Below are the snapshot of sample run triggering deffernt outputs (notice URL extensions)
That’s it.
Download Source Code
클래스에 EnvironmentAware 상속 받은다음에 Override setEnvironment 해주면 됩니다.
시점때문에 생기는 문제네요..
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @Configuration @PropertySource("classpath:myProperties.properties") public class MyConfiguration implements EnvironmentAware { private Environment environment; @Override public void setEnvironment(final Environment environment) { this.environment = environment; } public void myMethod() { final String myPropertyValue = environment.getProperty("myProperty"); // ... } } | cs |
1 2 3 4 5 6 7 8 9 10 | public class SystemLogApplication implements EnvironmentAware{ @Autowired private static Environment env; @Override public void setEnvironment(Environment environment) { // TODO Auto-generated method stub this.env = environment; } | cs |
1 2 3 4 5 6 7 8 9 10 11 | <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="callSettersOnNulls" value="true" /> <setting name="jdbcTypeForNull" value="NULL" /> </settings> <plugins> <plugin interceptor="kr.go.safepeople.config.interceptor.MybatisSqlLogInterceptor" /> </plugins> </configuration> | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | import java.lang.reflect.Field; import java.sql.Statement; import java.util.List; import java.util.Map; import java.util.Properties; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.ParameterMapping; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Plugin; import org.apache.ibatis.plugin.Signature; import org.apache.ibatis.session.ResultHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Intercepts({ @Signature(type=StatementHandler.class, method="update", args={Statement.class}) ,@Signature(type=StatementHandler.class, method="query", args={Statement.class, ResultHandler.class}) }) public class MybatisSqlLogInterceptor implements Interceptor { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Override public Object intercept(Invocation invocation) throws Throwable { // TODO Auto-generated method stub StatementHandler handler = (StatementHandler)invocation.getTarget(); BoundSql boundSql = handler.getBoundSql(); String sql = boundSql.getSql(); Object param = handler.getParameterHandler().getParameterObject(); if(param == null){ sql = sql.replaceFirst("\\?", "''"); }else{ if(param instanceof Integer || param instanceof Long || param instanceof Float || param instanceof Double){ sql = sql.replaceFirst("\\?", param.toString()); }else if(param instanceof String){ sql = sql.replaceFirst("\\?", "'" + param + "'"); }else if(param instanceof Map){ List<ParameterMapping> paramMapping = boundSql.getParameterMappings(); for(ParameterMapping mapping : paramMapping){ String propValue = mapping.getProperty(); Object value = ((Map) param).get(propValue); if(value != null){ if(value instanceof String){ sql = sql.replaceFirst("\\?", "'" + value + "'"); }else{ sql = sql.replaceFirst("\\?", value.toString()); } }else{ sql = sql.replaceFirst("\\?", "'null'"); } } }else{ List<ParameterMapping> paramMapping = boundSql.getParameterMappings(); Class<? extends Object> paramClass = param.getClass(); for(ParameterMapping mapping : paramMapping){ String propValue = mapping.getProperty(); Field field = paramClass.getDeclaredField(propValue); field.setAccessible(true); Class<?> javaType = mapping.getJavaType(); if(String.class == javaType){ sql = sql.replaceFirst("\\?", "'" + field.get(param) + "'"); }else{ sql = sql.replaceFirst("\\?", field.get(param).toString()); } } } } logger.debug("====================================================================="); logger.debug("SQL : "+sql); logger.debug("====================================================================="); return invocation.proceed(); } @Override public Object plugin(Object target) { // TODO Auto-generated method stub return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { // TODO Auto-generated method stub } } | cs |
In an earlier post, I blogged about the REST capabilities we added to Spring @MVC version 3.0. Later, Alef wrote about using the introduced functionality to add an Atom view to the Pet Clinic application. In this post, I would like to introduce the client-side capabilities we added in Milestone 2.
RestTemplate
The RestTemplate is the central Spring class for client-side HTTP access. Conceptually, it is very similar to the JdbcTemplate, JmsTemplate, and the various other templates found in the Spring Framework and other portfolio projects. This means, for instance, that the RestTemplate is thread-safe once constructed, and that you can use callbacks to customize its operations.
RestTemplate Methods
The main entry points of the template are named after the six main HTTP methods:
The names of these methods clearly indicate which HTTP method they invoke, while the second part of the name indicates what is returned. For instance, getForObject() will perform a GET, convert the HTTP response into an object type of your choice, and returns that object.postForLocation will do a POST, converting the given object into a HTTP request, and returns the response HTTP Location header where the newly created object can be found. As you can see, these methods try to enforce REST best practices.
URI Templates
Each of these methods takes a URI as first argument. That URI can be a URI template, and variables can be used to expand the template to a normal URI. The template variables can be passed in two forms: as a String variable arguments array, or as a Map<String, String>. The string varargs variant expands the given template variables in order, so that
String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21");
will perform a GET on http://example.com/hotels/42/bookings/21. The map variant expands the template based on variable name, and is therefore more useful when using many variables, or when a single variable is used multiple times. For example:
Map<String, String> vars = new HashMap<String, String>();
vars.put("hotel", "42");
vars.put("booking", "21");
String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", String.class, vars);
will also perform a GET on http://example.com/hotels/42/rooms/42.
HttpMessageConverters
Objects passed to and returned from the methods getForObject(), postForLocation(), andput() and are converted to HTTP requests and from HTTP responses by HttpMessageConverters. Converters for the main mime types and Java types are registered by default, but you can also write your own converter and plug it in the RestTemplate. In the example below, I will show you how that’s done.
Using the RestTemplate to retrieve photos from Flickr
Rather than going through the various methods of the RestTemplate, I will show you how to use it for retrieving pictures from Flickr, Yahoo!s online photo-sharing application. This sample application searches Flickr for photos that match a given search term. It then shows these pictures using a simple Swing UI. To run the application yourself, you will need to create a Flickr account and apply for an API key.
Searching for photos
Flickr exposes various APIs to manipulate its vast library of photos. The flickr.photos.searchmethod allows you to search for photos, by issuing a GET request onhttp://www.flickr.com/services/rest?method=flickr.photos.search&api+key=xxx&tags=penguins, where you enter your API key and the thing to search for (penguins in this case). As a result, you get back a XML document, describing the photos that conform to your query. Something like:
<photos page="2" pages="89" perpage="10" total="881">
<photo id="2636" owner="47058503995@N01"
secret="a123456" server="2" title="test_04"
ispublic="1" isfriend="0" isfamily="0" />
<photo id="2635" owner="47058503995@N01"
secret="b123456" server="2" title="test_03"
ispublic="0" isfriend="1" isfamily="1" />
<photo id="2633" owner="47058503995@N01"
secret="c123456" server="2" title="test_01"
ispublic="1" isfriend="0" isfamily="0" />
<photo id="2610" owner="12037949754@N01"
secret="d123456" server="2" title="00_tall"
ispublic="1" isfriend="0" isfamily="0" />
</photos>
Using the RestTemplate, retrieving such a document is quite trivial:
final String photoSearchUrl =
"http://www.flickr.com/services/rest?method=flickr.photos.search&api+key={api-key}&tags={tag}&per_page=10";
Source photos = restTemplate.getForObject(photoSearchUrl, Source.class, apiKey, searchTerm);
where apiKey and searchTerm are two Strings given on the command line. This method uses theSourceHttpMessageConverter to convert the HTTP XML response into ajavax.xml.transform.Source (Note that the SourceHttpMessageConverter was introduced shortly after we released Spring 3.0 M2, so you will have to get a recent snapshot (or the upcoming M3) to use it. The sample project available below is set up to retrieve these via Maven).
Retrieving the photos
Next, we’re going to use an XPath expression to retrieve all the photo elements of the document. For this, we are going to use the XPathTemplate from Spring Web Services. We are going to execute the //photo expressions, returning all photo elements occurring anywhere in the document. The NodeMapper is a callback interface, whose mapNode() method will be invoked for each photo element in the document. In this case, we are retrieving the server, id, andsecret attributes of this element, and use those to fill up a Map. Finally, we use the RestTemplate again, to retrieve the photo as a java.awt.image.BufferedImage. Thus when the XPath evaluation is done, the resulting imageList will contain an image for each photo in the XML document.
List<BufferedImage> imageList = xpathTemplate.evaluate("//photo", photos, new NodeMapper() {
public Object mapNode(Node node, int i) throws DOMException {
Element photo = (Element) node;
Map<String, String> variables = new HashMap<String, String>(3);
variables.put("server", photo.getAttribute("server"));
variables.put("id", photo.getAttribute("id"));
variables.put("secret", photo.getAttribute("secret"));
String photoUrl = "http://static.flickr.com/{server}/{id}_{secret}_m.jpg";
return restTemplate.getForObject(photoUrl, BufferedImage.class, variables);
}
});
For instance, given the XML document given above, the imageList will contain 4 images. The URL for the first image retrieved will be http://static.flickr.com/2/2636_ a123456_m.jpg, the second is http://static.flickr.com/2/2635_ b123456_m.jpg, etc.
Converting the images
There is one more thing that needs to be done in order for the code to work: we will need to write a HttpMessageConverter that is able to read from the HTTP response, and create aBufferedImagefrom that. Doing so with the Java Image I/O API is fairly simple, we just need to implement the read() method defined in the HttpMessageConverter interface. Overall, our simple converter looks like this:
public class BufferedImageHttpMessageConverter implements HttpMessageConverter<BufferedImage> {
public List<MediaType> getSupportedMediaTypes() {
return Collections.singletonList(new MediaType("image", "jpeg"));
}
public boolean supports(Class<? extends BufferedImage> clazz) {
return BufferedImage.class.equals(clazz);
}
public BufferedImage read(Class<BufferedImage> clazz, HttpInputMessage inputMessage) throws IOException {
return ImageIO.read(inputMessage.getBody());
}
public void write(BufferedImage image, HttpOutputMessage message) throws IOException {
throw new UnsupportedOperationException("Not implemented");
}
}
Note that we didn’t implement write() because we are not uploading images, just downloading them. Now we just have to plug this converter into the RestTemplate. We do that in the Spring application context:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="flickrClient" class="com.springsource.samples.resttemplate.FlickrClient">
<constructor-arg ref="restTemplate"/>
<constructor-arg ref="xpathTemplate"/>
</bean>
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="com.springsource.samples.resttemplate.BufferedImageHttpMessageConverter"/>
</list>
</property>
</bean>
<bean id="xpathTemplate" class="org.springframework.xml.xpath.Jaxp13XPathTemplate"/>
</beans>
Showing the photos
The final stage is to show the photos in a simple GUI. For this, we use Swing:
JFrame frame = new JFrame(searchTerm + " photos");
frame.setLayout(new GridLayout(2, imageList.size() / 2));
for (BufferedImage image : imageList) {
frame.add(new JLabel(new ImageIcon(image)));
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
which gives us the following:
Overall, I hope this post showed you how simple it can be to use the RestTemplate to interact with HTTP servers. In just under 30 lines of Java code, we created a GUI that shows pictures of everybody’s favorite bird: the penguin! Check out the RestTemplate and let us know what you think!
Downloads
A Maven project containing the code above can be downloaded here. Note that the project is based on a nightly snapshot build of Spring. The upcoming Milestone 3 of Spring will contain the necessary classes as well.
ava unlimited runtime class and resource redefinition.
The main purpose of this project is to avoid infamous change->restart + wait->check development lifecycle. Save&Reload during development should be standard and many other languages (including C#) contain this feature.
This project is still in a beta version.
Easy to start
Download and install latest DCEVM Java patch + agent jar and launch your application server with options -XXaltjvm=dcevm -javaagent:hotswap-agent.jar
to get basic setup. Optionally add hotswap-agent.properties to your application to configure plugins and agent behaviour.
Plugins
Each application framework (Spring, Hibernate, Logback, ...) needs special reloading mechanism to keep up-to-date after class redefinition (e.g. Hibernate configuration reload after new entity class is introduced). Hotswap agent works as a plugin system and ships preconfigured with all major framework plugins. It is easy to write your custom plugin even as part of your application.
Contribute
This project is very complex due to lot of supported frameworks and various versions. Community contribution is mandatory to keep it alive. You can start by creating a plugin inside your application or by writing an example/integration test. There is always need for documentation improvement :-). Thank you for any help!
Quick start:
Install
- download latest release of DCEVM Java patch and launch the installer (e.g.
java -jar installer-light.jar
). Currently you need to select correct installer for Java major version (7/8). - select java installation directory on your disc and press "Install DCEVM as altjvm" button. Java 1.7+ versions are supported.
- download latest release of Hotswap agent jar, unpack
hotswap-agent.jar
and put it anywhere on your disc. For example:C:\java\hotswap-agent.jar
Run your application
- add following command line java attributes:
-XXaltjvm=dcevm -javaagent:PATH_TO_AGENT\hotswap-agent.jar
(you need to replace PATH_TO_AGENT with an actual) directory. For examplejava -XXaltjvm=dcevm -javaagent:c:\java\hotswap-agent.jar YourApp
. See IntelliJ IDEA and Netbeans forum threads for IDE specific setup guides. - (optional) create a file named "hotswap-agent.properties" inside your resources directory, see available properties and default values: https://github.com/HotswapProjects/HotswapAgent/blob/master/hotswap-agent-core/src/main/resources/hotswap-agent.properties
start the application in debug mode, check that the agent and plugins are initialized correctly:
HOTSWAP AGENT: 9:49:29.548 INFO (org.hotswap.agent.HotswapAgent) - Loading Hotswap agent - unlimited runtime class redefinition. HOTSWAP AGENT: 9:49:29.725 INFO (org.hotswap.agent.config.PluginRegistry) - Discovered plugins: [org.hotswap.agent.plugin.hotswapper.HotswapperPlugin, org.hotswap.agent.plugin.jvm.AnonymousClassPatchPlugin, org.hotswap.agent.plugin.hibernate.HibernatePlugin, org.hotswap.agent.plugin.spring.SpringPlugin, org.hotswap.agent.plugin.jetty.JettyPlugin, org.hotswap.agent.plugin.tomcat.TomcatPlugin, org.hotswap.agent.plugin.zk.ZkPlugin, org.hotswap.agent.plugin.logback.LogbackPlugin] ... HOTSWAP AGENT: 9:49:38.700 INFO (org.hotswap.agent.plugin.spring.SpringPlugin) - Spring plugin initialized - Spring core version '3.2.3.RELEASE'
- save a changed resource and/or use the HotSwap feature of your IDE to reload changes
What is available?
- Enhanced Java Hotswap - change method body, add/rename a method, field, ... The only unsupported operation is hierarchy change (change the superclass or remove an interface).
- You can use standard Java Hotswap from IDE in debug mode to reload changed class
- or set autoHotswap property
-XXaltjvm=dcevm -javaagent:PATH_TO_AGENT\hotswap-agent.jar=autoHotswap=true
to reload changed classes after compilation. This setup allows even reload on production system without restart.
- Automatic configuration - all local classes and resources known to the running Java application are automatically discovered and watched for reload (all files on local filesystem, not inside JAR file).
- Extra classpath - Need change a runtime class inside dependent JAR? Use extraClasspath property to add any directory as a classpath to watch for class files.
- Reload resource after a change - resources from webapp directory are usually reloaded by application server. But what about other resources like src/main/resources? Use watchResources property to add any directory to watch for a resource change.
- Framework support - through plugin system, many frameworks are supported. New plugins can be easily added.
- Fast - until the plugin is initialized, it does not consume any resources or slow down the application (see Runtime overhead for more information)
Should you have any problems or questions, ask at HotswapAgent forum.
This project is similar to JRebel. Main differences are:
- HotswapAgent (DCEVM) supports Java8!
- HotswapAgent does not need any additional configuration for basic project setup.
- JRebel is currently more mature and contains more plugins.
- JRebel is neither open source nor free.
- JRebel modifies bytecode of all classes on reload. You need special IDE plugin to fix debugging.
- HotswapAgent extraClasspath is similar to JRebel configuration
- HotswapAgent adds watchResources configuration
Examples
See HotswapAgentExamples GitHub project. The purpose of an example application is:
- complex automate integration tests (check various configurations before a release, see
run-tests.sh
script) - to check "real world" plugin usage during plugin development (i.e. inside container)
- to provide working solution for typical application setups
- sandbox to simulate issues for existing or new setups
Feel free to fork/branch and create an application for your setup (functional, but as simple as possible). General setups will be merged into the master.
IDE support
None needed :) Really, all changes are transparent and all you need to do is to download patch+agent and setup your application / application server. Because we use standard java hotswap behaviour, your IDE will work as expected. However, we work on IDE plugins to help with download & configuration.
Configuration
The basic configuration set to reload classes and resources from classpath known to the running application (classloader). If you need a different configuration, add hotswap-agent.properties file to the classpath root (e.g. src/main/resources/hotswap-agent.properties
).
Detail documentation of available properties and default values can be found in the agent properties file
Hotswap agent command line options
Full syntax of command line options is:
-javaagent:[yourpath/]hotswap-agent.jar=[option1]=[value1],[option2]=[value2]
Hotswap agent accepts following options:
- autoHotswap=true - watch all .class files for change and automatically Hotswap the class in the running application (instead of running Hotswap from your IDE debugging session)
- disablePlugin=[pluginName] - disable a plugin. Note that this will completely forbid the plugin to load (opposite to disablePlugin option in hotswap-agent.properties, which will only disable the plugin for a classloader. You can repeat this option for every plugin to disable.
How does it work?
DCEVM
Hotswap agent does the work of reloading resources and framework configuration (Spring, Hibernate, ...), but it depends on standard Java hotswap mechanism to actually reload classes. Standard Java hotswap allows only method body change , which makes it practically unusable. DCEVM is a JRE patch witch allows almost any structural class change on hotswap (with an exception of a hierarchy change). Although hotswap agent works even with standard java, we recommend to use DCEVM (and all tutorials use DCEVM as target JVM).
Hotswap agent
Hotswap agent is a plugin container with plugin manager, plugin registry, and several agent services (e.g. to watch for class/resource change). It helps with common tasks and classloading issues. It scans classpath for class annotated with @Plugin annotation, injects agent services and registers reloading hooks. Runtime bytecode modification is provided by javaasist library.
Plugins
Plugins administered by Hotswap agent are usually targeted towards a specific framework. For example Spring plugin uses agent services to:
- Modify root Spring classes to get Spring contexts and registered scan path
- Watch for any resource change on a scan path
- Watch for a hotswap of a class file within a scan path package
- Reload bean definition after a change
- ... and many other
Packaged plugins:
- Hibernate (4x) - Reload Hibernate configuration after entity create/change.
- Spring (3x) - Reload Spring configuration after class definition/change.
- Jetty - add extra classpath to the app classloader. All versions supporting WebAppContext.getExtraClasspath should be supported.
- ZK (5x-7x) - ZK Framework (http://www.zkoss.org/). Change library properties default values to disable caches, maintains Label cache and bean resolver cache.
- Logback - Logback configuration reload
- Hotswapper - Watch for any class file change and reload (hotswap) it on the fly via Java Platform Debugger Architecture (JPDA)
- AnonymousClassPatch - Swap anonymous inner class names to avoid not compatible changes.
- ELResolver 2.2 (JuelEL, Appache Commons EL, Oracle EL 3.0)- clear ELResolver cache on class change. Support hotswap for #{...} expressions.
- Seam (2.2, 2.3) - flush JBoss reference cache. Support for properties file change (messages[])
- JBossModules - add extra class path to JBoss's module class loader.
- JSF (mojarra 2.1, 2.2) - support for application resource bundle files change (properties files).
- OsgiEquinox - Hotswap support for Eclipse plugin or Eclipse platform development.
- RESTEasy (2.x, 3.x) - reload @Path annotated classes on class create/change
- CDI/Weld - reload bean class definition after class create(managed beans)/change. Proxy bean redefinition after proxied class change. EAR support.
- WebObjects - Clear key value coding, component, action and validation caches after class change.
Find a detail documentation of each plugin in the plugin project main README.md file.
Runtime overhead
It really depends on how many frameworks you use and which caches are disabled. Example measurements for a large, real world enterprise application based on Spring + Hibernate, run on Jetty.
Setup | Startup time |
---|---|
Run (plain Java) | 23s |
Debug (plain Java) | 24s |
Debug (plain DCEVM) | 28s |
Agent - disabled all plugins | 31s |
Agent - all plugins | 35s |
How to write a plugin
You can write plugin directly as a part of your application. Set pluginPackages=your.plugin.package
inside your hotswap-agent.properties
configuration to discover @Plugin
annotated classes. You will also need agent JAR dependency to compile, but be careful NOT to add the JAR to your application, it must be loaded only as a javaagent. Maven dependency:
<dependency>
<groupId>org.hotswap.agent</groupId>
<artifactId>HotswapAgent</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
(Note that the JAR is not yet in central maven repository - you need to build it from source first).
See ExamplePlugin (part of TestApplication) to go through a commented simple plugin. Read agent readme to understand agent concepts. Check existing plugins source code for more examples.
Creating Release
Launch run-tests.sh
script in the main directory. Currently you have to setup JAVA_HOME location directory manually. At least Java 7 and Java 8 with DCEVM should be checked before a release. All automatic tests are set to fail the whole script in case of any single test failure.
Go to directory representing repository root. In case DCEVM is named dcevm
mvn release:prepare
mvn release:perform
In case your DCEVM is named differently i.e. server
mvn release:prepare -Darguments="-Ddcevm=server"
mvn release:perform -Darguments="-Ddcevm=server"
Plugin specific settings
OsgiEquinox / Eclipse RCP
OsgiEquinox / Eclipse plugin provides hotswap support for Eclipse plugin or Eclipse platform development (Do not confuse it with common development in Eclipse!).
Following options should be setup in eclipse.ini for debugee Eclipse instance:
# use application classloader for the framework
-Dosgi.frameworkParentClassloader=app
# development classpath that is added to each plugin classpath
-Dosgi.dev=[extra_classpath]
# use dcevm as JVM
-XXaltjvm=dcevm
# enable hotswapagent
-javaagent:PATH_TO_AGENT/hotswap-agent.jar
# enable remote debugging on port 8000
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000
extra_classpath points to directory with compiled classes. When a new class is compiled it is sent by remote debugger to HotswapAgent. HotswapAgent stores this file into extra_classpath directory.
It is also necessary to setup following hotswap-agent.properties:
extraClasspath=[extra_classpath]
osgiEquinox.debugMode=true
then connect the IDE debugger (eclipse, netbeans or idea) to port 8000 and happy hotswapping!
19.1 Introduction to Spring Framework JDBC
The value-add provided by the Spring Framework JDBC abstraction is perhaps best shown by the sequence of actions outlined in the table below. The table shows what actions Spring will take care of and which actions are the responsibility of you, the application developer.
Table 19.1. Spring JDBC - who does what?
Action | Spring | You |
---|---|---|
Define connection parameters. | X | |
Open the connection. | X | |
Specify the SQL statement. | X | |
Declare parameters and provide parameter values | X | |
Prepare and execute the statement. | X | |
Set up the loop to iterate through the results (if any). | X | |
Do the work for each iteration. | X | |
Process any exception. | X | |
Handle transactions. | X | |
Close the connection, statement and resultset. | X |
The Spring Framework takes care of all the low-level details that can make JDBC such a tedious API to develop with.
19.1.1 Choosing an approach for JDBC database access
You can choose among several approaches to form the basis for your JDBC database access. In addition to three flavors of the JdbcTemplate, a new SimpleJdbcInsert and SimplejdbcCall approach optimizes database metadata, and the RDBMS Object style takes a more object-oriented approach similar to that of JDO Query design. Once you start using one of these approaches, you can still mix and match to include a feature from a different approach. All approaches require a JDBC 2.0-compliant driver, and some advanced features require a JDBC 3.0 driver.
- JdbcTemplate is the classic Spring JDBC approach and the most popular. This "lowest level" approach and all others use a JdbcTemplate under the covers.
- NamedParameterJdbcTemplate wraps a
JdbcTemplate
to provide named parameters instead of the traditional JDBC "?" placeholders. This approach provides better documentation and ease of use when you have multiple parameters for an SQL statement. - SimpleJdbcInsert and SimpleJdbcCall optimize database metadata to limit the amount of necessary configuration. This approach simplifies coding so that you only need to provide the name of the table or procedure and provide a map of parameters matching the column names. This only works if the database provides adequate metadata. If the database doesn’t provide this metadata, you will have to provide explicit configuration of the parameters.
- RDBMS Objects including MappingSqlQuery, SqlUpdate and StoredProcedure requires you to create reusable and thread-safe objects during initialization of your data access layer. This approach is modeled after JDO Query wherein you define your query string, declare parameters, and compile the query. Once you do that, execute methods can be called multiple times with various parameter values passed in.
19.1.2 Package hierarchy
The Spring Framework’s JDBC abstraction framework consists of four different packages, namely core
, datasource
, object
, and support
.
The org.springframework.jdbc.core
package contains the JdbcTemplate
class and its various callback interfaces, plus a variety of related classes. A subpackage named org.springframework.jdbc.core.simple
contains the SimpleJdbcInsert
and SimpleJdbcCall
classes. Another subpackage named org.springframework.jdbc.core.namedparam
contains the NamedParameterJdbcTemplate
class and the related support classes. SeeSection 19.2, “Using the JDBC core classes to control basic JDBC processing and error handling”, Section 19.4, “JDBC batch operations”, and Section 19.5, “Simplifying JDBC operations with the SimpleJdbc classes”.
The org.springframework.jdbc.datasource
package contains a utility class for easy DataSource
access, and various simple DataSource
implementations that can be used for testing and running unmodified JDBC code outside of a Java EE container. A subpackage namedorg.springfamework.jdbc.datasource.embedded
provides support for creating embedded databases using Java database engines such as HSQL, H2, and Derby. See Section 19.3, “Controlling database connections” and Section 19.8, “Embedded database support”.
The org.springframework.jdbc.object
package contains classes that represent RDBMS queries, updates, and stored procedures as thread-safe, reusable objects. See Section 19.6, “Modeling JDBC operations as Java objects”. This approach is modeled by JDO, although objects returned by queries are naturally disconnected from the database. This higher level of JDBC abstraction depends on the lower-level abstraction in theorg.springframework.jdbc.core
package.
The org.springframework.jdbc.support
package provides SQLException
translation functionality and some utility classes. Exceptions thrown during JDBC processing are translated to exceptions defined in the org.springframework.dao
package. This means that code using the Spring JDBC abstraction layer does not need to implement JDBC or RDBMS-specific error handling. All translated exceptions are unchecked, which gives you the option of catching the exceptions from which you can recover while allowing other exceptions to be propagated to the caller. See Section 19.2.3, “SQLExceptionTranslator”.
19.2 Using the JDBC core classes to control basic JDBC processing and error handling
19.2.1 JdbcTemplate
The JdbcTemplate
class is the central class in the JDBC core package. It handles the creation and release of resources, which helps you avoid common errors such as forgetting to close the connection. It performs the basic tasks of the core JDBC workflow such as statement creation and execution, leaving application code to provide SQL and extract results. The JdbcTemplate
class executes SQL queries, update statements and stored procedure calls, performs iteration over ResultSet
s and extraction of returned parameter values. It also catches JDBC exceptions and translates them to the generic, more informative, exception hierarchy defined in the org.springframework.dao
package.
When you use the JdbcTemplate
for your code, you only need to implement callback interfaces, giving them a clearly defined contract. ThePreparedStatementCreator
callback interface creates a prepared statement given a Connection
provided by this class, providing SQL and any necessary parameters. The same is true for the CallableStatementCreator
interface, which creates callable statements. The RowCallbackHandler
interface extracts values from each row of a ResultSet
.
The JdbcTemplate
can be used within a DAO implementation through direct instantiation with a DataSource
reference, or be configured in a Spring IoC container and given to DAOs as a bean reference.
The |
All SQL issued by this class is logged at the DEBUG
level under the category corresponding to the fully qualified class name of the template instance (typicallyJdbcTemplate
, but it may be different if you are using a custom subclass of the JdbcTemplate
class).
Examples of JdbcTemplate class usage
This section provides some examples of JdbcTemplate
class usage. These examples are not an exhaustive list of all of the functionality exposed by theJdbcTemplate
; see the attendant javadocs for that.
Querying (SELECT)
Here is a simple query for getting the number of rows in a relation:
int rowCount = this.jdbcTemplate.queryForObject("select count(*) from t_actor", Integer.class);
A simple query using a bind variable:
int countOfActorsNamedJoe = this.jdbcTemplate.queryForObject( "select count(*) from t_actor where first_name = ?", Integer.class, "Joe");
Querying for a String
:
String lastName = this.jdbcTemplate.queryForObject( "select last_name from t_actor where id = ?", new Object[]{1212L}, String.class);
Querying and populating a single domain object:
Actor actor = this.jdbcTemplate.queryForObject( "select first_name, last_name from t_actor where id = ?", new Object[]{1212L}, new RowMapper<Actor>() { public Actor mapRow(ResultSet rs, int rowNum) throws SQLException { Actor actor = new Actor(); actor.setFirstName(rs.getString("first_name")); actor.setLastName(rs.getString("last_name")); return actor; } });
Querying and populating a number of domain objects:
List<Actor> actors = this.jdbcTemplate.query( "select first_name, last_name from t_actor", new RowMapper<Actor>() { public Actor mapRow(ResultSet rs, int rowNum) throws SQLException { Actor actor = new Actor(); actor.setFirstName(rs.getString("first_name")); actor.setLastName(rs.getString("last_name")); return actor; } });
If the last two snippets of code actually existed in the same application, it would make sense to remove the duplication present in the two RowMapper
anonymous inner classes, and extract them out into a single class (typically a static
nested class) that can then be referenced by DAO methods as needed. For example, it may be better to write the last code snippet as follows:
public List<Actor> findAllActors() { return this.jdbcTemplate.query( "select first_name, last_name from t_actor", new ActorMapper()); } private static final class ActorMapper implements RowMapper<Actor> { public Actor mapRow(ResultSet rs, int rowNum) throws SQLException { Actor actor = new Actor(); actor.setFirstName(rs.getString("first_name")); actor.setLastName(rs.getString("last_name")); return actor; } }
Updating (INSERT/UPDATE/DELETE) with jdbcTemplate
You use the update(..)
method to perform insert, update and delete operations. Parameter values are usually provided as var args or alternatively as an object array.
this.jdbcTemplate.update( "insert into t_actor (first_name, last_name) values (?, ?)", "Leonor", "Watling");
this.jdbcTemplate.update( "update t_actor set last_name = ? where id = ?", "Banjo", 5276L);
this.jdbcTemplate.update( "delete from actor where id = ?", Long.valueOf(actorId));
Other jdbcTemplate operations
You can use the execute(..)
method to execute any arbitrary SQL, and as such the method is often used for DDL statements. It is heavily overloaded with variants taking callback interfaces, binding variable arrays, and so on.
this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");
The following example invokes a simple stored procedure. More sophisticated stored procedure support is covered later.
this.jdbcTemplate.update( "call SUPPORT.REFRESH_ACTORS_SUMMARY(?)", Long.valueOf(unionId));
JdbcTemplate best practices
Instances of the JdbcTemplate
class are threadsafe once configured. This is important because it means that you can configure a single instance of aJdbcTemplate
and then safely inject this shared reference into multiple DAOs (or repositories). The JdbcTemplate
is stateful, in that it maintains a reference to a DataSource
, but this state is not conversational state.
A common practice when using the JdbcTemplate
class (and the associated NamedParameterJdbcTemplate
classes) is to configure a DataSource
in your Spring configuration file, and then dependency-inject that shared DataSource
bean into your DAO classes; the JdbcTemplate
is created in the setter for theDataSource
. This leads to DAOs that look in part like the following:
public class JdbcCorporateEventDao implements CorporateEventDao { private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } // JDBC-backed implementations of the methods on the CorporateEventDao follow... }
The corresponding configuration might look like this.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="corporateEventDao" class="com.example.JdbcCorporateEventDao"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <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> <context:property-placeholder location="jdbc.properties"/> </beans>
An alternative to explicit configuration is to use component-scanning and annotation support for dependency injection. In this case you annotate the class with@Repository
(which makes it a candidate for component-scanning) and annotate the DataSource
setter method with @Autowired
.
@Repository public class JdbcCorporateEventDao implements CorporateEventDao { private JdbcTemplate jdbcTemplate; @Autowired public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } // JDBC-backed implementations of the methods on the CorporateEventDao follow... }
The corresponding XML configuration file would look like the following:
<?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- Scans within the base package of the application for @Component classes to configure as beans --> <context:component-scan base-package="org.springframework.docs.test" /> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <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> <context:property-placeholder location="jdbc.properties"/> </beans>
If you are using Spring’s JdbcDaoSupport
class, and your various JDBC-backed DAO classes extend from it, then your sub-class inherits asetDataSource(..)
method from the JdbcDaoSupport
class. You can choose whether to inherit from this class. The JdbcDaoSupport
class is provided as a convenience only.
Regardless of which of the above template initialization styles you choose to use (or not), it is seldom necessary to create a new instance of a JdbcTemplate
class each time you want to execute SQL. Once configured, a JdbcTemplate
instance is threadsafe. You may want multiple JdbcTemplate
instances if your application accesses multiple databases, which requires multiple DataSources
, and subsequently multiple differently configured JdbcTemplates
.
19.2.2 NamedParameterJdbcTemplate
The NamedParameterJdbcTemplate
class adds support for programming JDBC statements using named parameters, as opposed to programming JDBC statements using only classic placeholder ( '?'
) arguments. The NamedParameterJdbcTemplate
class wraps a JdbcTemplate
, and delegates to the wrapped JdbcTemplate
to do much of its work. This section describes only those areas of the NamedParameterJdbcTemplate
class that differ from theJdbcTemplate
itself; namely, programming JDBC statements using named parameters.
// some JDBC-backed DAO class... private NamedParameterJdbcTemplate namedParameterJdbcTemplate; public void setDataSource(DataSource dataSource) { this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); } public int countOfActorsByFirstName(String firstName) { String sql = "select count(*) from T_ACTOR where first_name = :first_name"; SqlParameterSource namedParameters = new MapSqlParameterSource("first_name", firstName); return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class); }
Notice the use of the named parameter notation in the value assigned to the sql
variable, and the corresponding value that is plugged into thenamedParameters
variable (of type MapSqlParameterSource
).
Alternatively, you can pass along named parameters and their corresponding values to a NamedParameterJdbcTemplate
instance by using the Map
-based style.The remaining methods exposed by the NamedParameterJdbcOperations
and implemented by the NamedParameterJdbcTemplate
class follow a similar pattern and are not covered here.
The following example shows the use of the Map
-based style.
// some JDBC-backed DAO class... private NamedParameterJdbcTemplate namedParameterJdbcTemplate; public void setDataSource(DataSource dataSource) { this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); } public int countOfActorsByFirstName(String firstName) { String sql = "select count(*) from T_ACTOR where first_name = :first_name"; Map<String, String> namedParameters = Collections.singletonMap("first_name", firstName); return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class); }
One nice feature related to the NamedParameterJdbcTemplate
(and existing in the same Java package) is the SqlParameterSource
interface. You have already seen an example of an implementation of this interface in one of the previous code snippet (the MapSqlParameterSource
class). AnSqlParameterSource
is a source of named parameter values to a NamedParameterJdbcTemplate
. The MapSqlParameterSource
class is a very simple implementation that is simply an adapter around a java.util.Map
, where the keys are the parameter names and the values are the parameter values.
Another SqlParameterSource
implementation is the BeanPropertySqlParameterSource
class. This class wraps an arbitrary JavaBean (that is, an instance of a class that adheres to the JavaBean conventions), and uses the properties of the wrapped JavaBean as the source of named parameter values.
public class Actor { private Long id; private String firstName; private String lastName; public String getFirstName() { return this.firstName; } public String getLastName() { return this.lastName; } public Long getId() { return this.id; } // setters omitted... }
// some JDBC-backed DAO class... private NamedParameterJdbcTemplate namedParameterJdbcTemplate; public void setDataSource(DataSource dataSource) { this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); } public int countOfActors(Actor exampleActor) { // notice how the named parameters match the properties of the above 'Actor' class String sql = "select count(*) from T_ACTOR where first_name = :firstName and last_name = :lastName"; SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(exampleActor); return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class); }
Remember that the NamedParameterJdbcTemplate
class wraps a classic JdbcTemplate
template; if you need access to the wrapped JdbcTemplate
instance to access functionality only present in the JdbcTemplate
class, you can use the getJdbcOperations()
method to access the wrappedJdbcTemplate
through the JdbcOperations
interface.
See also the section called “JdbcTemplate best practices” for guidelines on using the NamedParameterJdbcTemplate
class in the context of an application.
19.2.3 SQLExceptionTranslator
SQLExceptionTranslator
is an interface to be implemented by classes that can translate between SQLExceptions
and Spring’s ownorg.springframework.dao.DataAccessException
, which is agnostic in regard to data access strategy. Implementations can be generic (for example, using SQLState codes for JDBC) or proprietary (for example, using Oracle error codes) for greater precision.
SQLErrorCodeSQLExceptionTranslator
is the implementation of SQLExceptionTranslator
that is used by default. This implementation uses specific vendor codes. It is more precise than the SQLState
implementation. The error code translations are based on codes held in a JavaBean type class calledSQLErrorCodes
. This class is created and populated by an SQLErrorCodesFactory
which as the name suggests is a factory for creating SQLErrorCodes
based on the contents of a configuration file named sql-error-codes.xml
. This file is populated with vendor codes and based on theDatabaseProductName
taken from the DatabaseMetaData
. The codes for the actual database you are using are used.
The SQLErrorCodeSQLExceptionTranslator
applies matching rules in the following sequence:
The |
- Any custom translation implemented by a subclass. Normally the provided concrete
SQLErrorCodeSQLExceptionTranslator
is used so this rule does not apply. It only applies if you have actually provided a subclass implementation. - Any custom implementation of the
SQLExceptionTranslator
interface that is provided as thecustomSqlExceptionTranslator
property of theSQLErrorCodes
class. - The list of instances of the
CustomSQLErrorCodesTranslation
class, provided for thecustomTranslations
property of theSQLErrorCodes
class, are searched for a match. - Error code matching is applied.
- Use the fallback translator.
SQLExceptionSubclassTranslator
is the default fallback translator. If this translation is not available then the next fallback translator is theSQLStateSQLExceptionTranslator
.
You can extend SQLErrorCodeSQLExceptionTranslator:
public class CustomSQLErrorCodesTranslator extends SQLErrorCodeSQLExceptionTranslator { protected DataAccessException customTranslate(String task, String sql, SQLException sqlex) { if (sqlex.getErrorCode() == -12345) { return new DeadlockLoserDataAccessException(task, sqlex); } return null; } }
In this example, the specific error code -12345
is translated and other errors are left to be translated by the default translator implementation. To use this custom translator, it is necessary to pass it to the JdbcTemplate
through the method setExceptionTranslator
and to use this JdbcTemplate
for all of the data access processing where this translator is needed. Here is an example of how this custom translator can be used:
private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { // create a JdbcTemplate and set data source this.jdbcTemplate = new JdbcTemplate(); this.jdbcTemplate.setDataSource(dataSource); // create a custom translator and set the DataSource for the default translation lookup CustomSQLErrorCodesTranslator tr = new CustomSQLErrorCodesTranslator(); tr.setDataSource(dataSource); this.jdbcTemplate.setExceptionTranslator(tr); } public void updateShippingCharge(long orderId, long pct) { // use the prepared JdbcTemplate for this update this.jdbcTemplate.update("update orders" + " set shipping_charge = shipping_charge * ? / 100" + " where id = ?", pct, orderId); }
The custom translator is passed a data source in order to look up the error codes in sql-error-codes.xml
.
19.2.4 Executing statements
Executing an SQL statement requires very little code. You need a DataSource
and a JdbcTemplate
, including the convenience methods that are provided with the JdbcTemplate
. The following example shows what you need to include for a minimal but fully functional class that creates a new table:
import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; public class ExecuteAStatement { private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } public void doExecute() { this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))"); } }
19.2.5 Running queries
Some query methods return a single value. To retrieve a count or a specific value from one row, use queryForObject(..)
. The latter converts the returned JDBC Type
to the Java class that is passed in as an argument. If the type conversion is invalid, then an InvalidDataAccessApiUsageException
is thrown. Here is an example that contains two query methods, one for an int
and one that queries for a String
.
import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; public class RunAQuery { private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } public int getCount() { return this.jdbcTemplate.queryForObject("select count(*) from mytable", Integer.class); } public String getName() { return this.jdbcTemplate.queryForObject("select name from mytable", String.class); } }
In addition to the single result query methods, several methods return a list with an entry for each row that the query returned. The most generic method isqueryForList(..)
which returns a List
where each entry is a Map
with each entry in the map representing the column value for that row. If you add a method to the above example to retrieve a list of all the rows, it would look like this:
private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } public List<Map<String, Object>> getList() { return this.jdbcTemplate.queryForList("select * from mytable"); }
The list returned would look something like this:
[{name=Bob, id=1}, {name=Mary, id=2}]
19.2.6 Updating the database
The following example shows a column updated for a certain primary key. In this example, an SQL statement has placeholders for row parameters. The parameter values can be passed in as varargs or alternatively as an array of objects. Thus primitives should be wrapped in the primitive wrapper classes explicitly or using auto-boxing.
import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; public class ExecuteAnUpdate { private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } public void setName(int id, String name) { this.jdbcTemplate.update("update mytable set name = ? where id = ?", name, id); } }
19.2.7 Retrieving auto-generated keys
An update()
convenience method supports the retrieval of primary keys generated by the database. This support is part of the JDBC 3.0 standard; see Chapter 13.6 of the specification for details. The method takes a PreparedStatementCreator
as its first argument, and this is the way the required insert statement is specified. The other argument is a KeyHolder
, which contains the generated key on successful return from the update. There is not a standard single way to create an appropriate PreparedStatement
(which explains why the method signature is the way it is). The following example works on Oracle but may not work on other platforms:
final String INSERT_SQL = "insert into my_test (name) values(?)"; final String name = "Rob"; KeyHolder keyHolder = new GeneratedKeyHolder(); jdbcTemplate.update( new PreparedStatementCreator() { public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { PreparedStatement ps = connection.prepareStatement(INSERT_SQL, new String[] {"id"}); ps.setString(1, name); return ps; } }, keyHolder); // keyHolder.getKey() now contains the generated key
19.3 Controlling database connections
19.3.1 DataSource
Spring obtains a connection to the database through a DataSource
. A DataSource
is part of the JDBC specification and is a generalized connection factory. It allows a container or a framework to hide connection pooling and transaction management issues from the application code. As a developer, you need not know details about how to connect to the database; that is the responsibility of the administrator that sets up the datasource. You most likely fill both roles as you develop and test code, but you do not necessarily have to know how the production data source is configured.
When using Spring’s JDBC layer, you obtain a data source from JNDI or you configure your own with a connection pool implementation provided by a third party. Popular implementations are Apache Jakarta Commons DBCP and C3P0. Implementations in the Spring distribution are meant only for testing purposes and do not provide pooling.
This section uses Spring’s DriverManagerDataSource
implementation, and several additional implementations are covered later.
Only use the |
You obtain a connection with DriverManagerDataSource
as you typically obtain a JDBC connection. Specify the fully qualified classname of the JDBC driver so that the DriverManager
can load the driver class. Next, provide a URL that varies between JDBC drivers. (Consult the documentation for your driver for the correct value.) Then provide a username and a password to connect to the database. Here is an example of how to configure a DriverManagerDataSource
in Java code:
DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); dataSource.setUrl("jdbc:hsqldb:hsql://localhost:"); dataSource.setUsername("sa"); dataSource.setPassword("");
Here is the corresponding XML configuration:
<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> <context:property-placeholder location="jdbc.properties"/>
The following examples show the basic connectivity and configuration for DBCP and C3P0. To learn about more options that help control the pooling features, see the product documentation for the respective connection pooling implementations.
DBCP configuration:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <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> <context:property-placeholder location="jdbc.properties"/>
C3P0 configuration:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driverClassName}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <context:property-placeholder location="jdbc.properties"/>
19.3.2 DataSourceUtils
The DataSourceUtils
class is a convenient and powerful helper class that provides static
methods to obtain connections from JNDI and close connections if necessary. It supports thread-bound connections with, for example, DataSourceTransactionManager
.
19.3.3 SmartDataSource
The SmartDataSource
interface should be implemented by classes that can provide a connection to a relational database. It extends the DataSource
interface to allow classes using it to query whether the connection should be closed after a given operation. This usage is efficient when you know that you will reuse a connection.
19.3.4 AbstractDataSource
AbstractDataSource
is an abstract
base class for Spring’s DataSource
implementations that implements code that is common to all DataSource
implementations. You extend the AbstractDataSource
class if you are writing your own DataSource
implementation.
19.3.5 SingleConnectionDataSource
The SingleConnectionDataSource
class is an implementation of the SmartDataSource
interface that wraps a single Connection
that is not closed after each use. Obviously, this is not multi-threading capable.
If any client code calls close
in the assumption of a pooled connection, as when using persistence tools, set the suppressClose
property to true
. This setting returns a close-suppressing proxy wrapping the physical connection. Be aware that you will not be able to cast this to a native Oracle Connection
or the like anymore.
This is primarily a test class. For example, it enables easy testing of code outside an application server, in conjunction with a simple JNDI environment. In contrast to DriverManagerDataSource
, it reuses the same connection all the time, avoiding excessive creation of physical connections.
19.3.6 DriverManagerDataSource
The DriverManagerDataSource
class is an implementation of the standard DataSource
interface that configures a plain JDBC driver through bean properties, and returns a new Connection
every time.
This implementation is useful for test and stand-alone environments outside of a Java EE container, either as a DataSource
bean in a Spring IoC container, or in conjunction with a simple JNDI environment. Pool-assuming Connection.close()
calls will simply close the connection, so any DataSource
-aware persistence code should work. However, using JavaBean-style connection pools such as commons-dbcp
is so easy, even in a test environment, that it is almost always preferable to use such a connection pool over DriverManagerDataSource
.
19.3.7 TransactionAwareDataSourceProxy
TransactionAwareDataSourceProxy
is a proxy for a target DataSource
, which wraps that target DataSource
to add awareness of Spring-managed transactions. In this respect, it is similar to a transactional JNDI DataSource
as provided by a Java EE server.
It is rarely desirable to use this class, except when already existing code that must be called and passed a standard JDBC |
(See the TransactionAwareDataSourceProxy
javadocs for more details.)
19.3.8 DataSourceTransactionManager
The DataSourceTransactionManager
class is a PlatformTransactionManager
implementation for single JDBC datasources. It binds a JDBC connection from the specified data source to the currently executing thread, potentially allowing for one thread connection per data source.
Application code is required to retrieve the JDBC connection through DataSourceUtils.getConnection(DataSource)
instead of Java EE’s standardDataSource.getConnection
. It throws unchecked org.springframework.dao
exceptions instead of checked SQLExceptions
. All framework classes likeJdbcTemplate
use this strategy implicitly. If not used with this transaction manager, the lookup strategy behaves exactly like the common one - it can thus be used in any case.
The DataSourceTransactionManager
class supports custom isolation levels, and timeouts that get applied as appropriate JDBC statement query timeouts. To support the latter, application code must either use JdbcTemplate
or call the DataSourceUtils.applyTransactionTimeout(..)
method for each created statement.
This implementation can be used instead of JtaTransactionManager
in the single resource case, as it does not require the container to support JTA. Switching between both is just a matter of configuration, if you stick to the required connection lookup pattern. JTA does not support custom isolation levels!
19.3.9 NativeJdbcExtractor
Sometimes you need to access vendor specific JDBC methods that differ from the standard JDBC API. This can be problematic if you are running in an application server or with a DataSource
that wraps the Connection
, Statement
and ResultSet
objects with its own wrapper objects. To gain access to the native objects you can configure your JdbcTemplate
or OracleLobHandler
with a NativeJdbcExtractor
.
The NativeJdbcExtractor
comes in a variety of flavors to match your execution environment:
- SimpleNativeJdbcExtractor
- C3P0NativeJdbcExtractor
- CommonsDbcpNativeJdbcExtractor
- JBossNativeJdbcExtractor
- WebLogicNativeJdbcExtractor
- WebSphereNativeJdbcExtractor
- XAPoolNativeJdbcExtractor
Usually the SimpleNativeJdbcExtractor
is sufficient for unwrapping a Connection
object in most environments. See the javadocs for more details.
19.4 JDBC batch operations
Most JDBC drivers provide improved performance if you batch multiple calls to the same prepared statement. By grouping updates into batches you limit the number of round trips to the database.
19.4.1 Basic batch operations with the JdbcTemplate
You accomplish JdbcTemplate
batch processing by implementing two methods of a special interface, BatchPreparedStatementSetter
, and passing that in as the second parameter in your batchUpdate
method call. Use the getBatchSize
method to provide the size of the current batch. Use the setValues
method to set the values for the parameters of the prepared statement. This method will be called the number of times that you specified in the getBatchSize
call. The following example updates the actor table based on entries in a list. The entire list is used as the batch in this example:
public class JdbcActorDao implements ActorDao { private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } public int[] batchUpdate(final List<Actor> actors) { int[] updateCounts = jdbcTemplate.batchUpdate("update t_actor set first_name = ?, " + "last_name = ? where id = ?", new BatchPreparedStatementSetter() { public void setValues(PreparedStatement ps, int i) throws SQLException { ps.setString(1, actors.get(i).getFirstName()); ps.setString(2, actors.get(i).getLastName()); ps.setLong(3, actors.get(i).getId().longValue()); } public int getBatchSize() { return actors.size(); } }); return updateCounts; } // ... additional methods }
If you are processing a stream of updates or reading from a file, then you might have a preferred batch size, but the last batch might not have that number of entries. In this case you can use the InterruptibleBatchPreparedStatementSetter
interface, which allows you to interrupt a batch once the input source is exhausted. The isBatchExhausted
method allows you to signal the end of the batch.
19.4.2 Batch operations with a List of objects
Both the JdbcTemplate
and the NamedParameterJdbcTemplate
provides an alternate way of providing the batch update. Instead of implementing a special batch interface, you provide all parameter values in the call as a list. The framework loops over these values and uses an internal prepared statement setter. The API varies depending on whether you use named parameters. For the named parameters you provide an array of SqlParameterSource
, one entry for each member of the batch. You can use the SqlParameterSource.createBatch
method to create this array, passing in either an array of JavaBeans or an array of Maps containing the parameter values.
This example shows a batch update using named parameters:
public class JdbcActorDao implements ActorDao { private NamedParameterTemplate namedParameterJdbcTemplate; public void setDataSource(DataSource dataSource) { this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); } public int[] batchUpdate(final List<Actor> actors) { SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(actors.toArray()); int[] updateCounts = namedParameterJdbcTemplate.batchUpdate( "update t_actor set first_name = :firstName, last_name = :lastName where id = :id", batch); return updateCounts; } // ... additional methods }
For an SQL statement using the classic "?" placeholders, you pass in a list containing an object array with the update values. This object array must have one entry for each placeholder in the SQL statement, and they must be in the same order as they are defined in the SQL statement.
The same example using classic JDBC "?" placeholders:
public class JdbcActorDao implements ActorDao { private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } public int[] batchUpdate(final List<Actor> actors) { List<Object[]> batch = new ArrayList<Object[]>(); for (Actor actor : actors) { Object[] values = new Object[] { actor.getFirstName(), actor.getLastName(), actor.getId()}; batch.add(values); } int[] updateCounts = jdbcTemplate.batchUpdate( "update t_actor set first_name = ?, last_name = ? where id = ?", batch); return updateCounts; } // ... additional methods }
All of the above batch update methods return an int array containing the number of affected rows for each batch entry. This count is reported by the JDBC driver. If the count is not available, the JDBC driver returns a -2 value.
19.4.3 Batch operations with multiple batches
The last example of a batch update deals with batches that are so large that you want to break them up into several smaller batches. You can of course do this with the methods mentioned above by making multiple calls to the batchUpdate
method, but there is now a more convenient method. This method takes, in addition to the SQL statement, a Collection of objects containing the parameters, the number of updates to make for each batch and aParameterizedPreparedStatementSetter
to set the values for the parameters of the prepared statement. The framework loops over the provided values and breaks the update calls into batches of the size specified.
This example shows a batch update using a batch size of 100:
public class JdbcActorDao implements ActorDao { private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } public int[][] batchUpdate(final Collection<Actor> actors) { int[][] updateCounts = jdbcTemplate.batchUpdate( "update t_actor set first_name = ?, last_name = ? where id = ?", actors, 100, new ParameterizedPreparedStatementSetter<Actor>() { public void setValues(PreparedStatement ps, Actor argument) throws SQLException { ps.setString(1, argument.getFirstName()); ps.setString(2, argument.getLastName()); ps.setLong(3, argument.getId().longValue()); } }); return updateCounts; } // ... additional methods }
The batch update methods for this call returns an array of int arrays containing an array entry for each batch with an array of the number of affected rows for each update. The top level array’s length indicates the number of batches executed and the second level array’s length indicates the number of updates in that batch. The number of updates in each batch should be the batch size provided for all batches except for the last one that might be less, depending on the total number of update objects provided. The update count for each update statement is the one reported by the JDBC driver. If the count is not available, the JDBC driver returns a -2 value.
19.5 Simplifying JDBC operations with the SimpleJdbc classes
The SimpleJdbcInsert
and SimpleJdbcCall
classes provide a simplified configuration by taking advantage of database metadata that can be retrieved through the JDBC driver. This means there is less to configure up front, although you can override or turn off the metadata processing if you prefer to provide all the details in your code.
19.5.1 Inserting data using SimpleJdbcInsert
Let’s start by looking at the SimpleJdbcInsert
class with the minimal amount of configuration options. You should instantiate the SimpleJdbcInsert
in the data access layer’s initialization method. For this example, the initializing method is the setDataSource
method. You do not need to subclass theSimpleJdbcInsert
class; simply create a new instance and set the table name using the withTableName
method. Configuration methods for this class follow the "fluid" style that returns the instance of the SimpleJdbcInsert
, which allows you to chain all configuration methods. This example uses only one configuration method; you will see examples of multiple ones later.
public class JdbcActorDao implements ActorDao { private JdbcTemplate jdbcTemplate; private SimpleJdbcInsert insertActor; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); this.insertActor = new SimpleJdbcInsert(dataSource).withTableName("t_actor"); } public void add(Actor actor) { Map<String, Object> parameters = new HashMap<String, Object>(3); parameters.put("id", actor.getId()); parameters.put("first_name", actor.getFirstName()); parameters.put("last_name", actor.getLastName()); insertActor.execute(parameters); } // ... additional methods }
The execute method used here takes a plain java.utils.Map
as its only parameter. The important thing to note here is that the keys used for the Map must match the column names of the table as defined in the database. This is because we read the metadata in order to construct the actual insert statement.
19.5.2 Retrieving auto-generated keys using SimpleJdbcInsert
This example uses the same insert as the preceding, but instead of passing in the id it retrieves the auto-generated key and sets it on the new Actor object. When you create the SimpleJdbcInsert
, in addition to specifying the table name, you specify the name of the generated key column with theusingGeneratedKeyColumns
method.
public class JdbcActorDao implements ActorDao { private JdbcTemplate jdbcTemplate; private SimpleJdbcInsert insertActor; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); this.insertActor = new SimpleJdbcInsert(dataSource) .withTableName("t_actor") .usingGeneratedKeyColumns("id"); } public void add(Actor actor) { Map<String, Object> parameters = new HashMap<String, Object>(2); parameters.put("first_name", actor.getFirstName()); parameters.put("last_name", actor.getLastName()); Number newId = insertActor.executeAndReturnKey(parameters); actor.setId(newId.longValue()); } // ... additional methods }
The main difference when executing the insert by this second approach is that you do not add the id to the Map and you call the executeAndReturnKey
method. This returns a java.lang.Number
object with which you can create an instance of the numerical type that is used in our domain class. You cannot rely on all databases to return a specific Java class here; java.lang.Number
is the base class that you can rely on. If you have multiple auto-generated columns, or the generated values are non-numeric, then you can use a KeyHolder
that is returned from the executeAndReturnKeyHolder
method.
19.5.3 Specifying columns for a SimpleJdbcInsert
You can limit the columns for an insert by specifying a list of column names with the usingColumns
method:
public class JdbcActorDao implements ActorDao { private JdbcTemplate jdbcTemplate; private SimpleJdbcInsert insertActor; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); this.insertActor = new SimpleJdbcInsert(dataSource) .withTableName("t_actor") .usingColumns("first_name", "last_name") .usingGeneratedKeyColumns("id"); } public void add(Actor actor) { Map<String, Object> parameters = new HashMap<String, Object>(2); parameters.put("first_name", actor.getFirstName()); parameters.put("last_name", actor.getLastName()); Number newId = insertActor.executeAndReturnKey(parameters); actor.setId(newId.longValue()); } // ... additional methods }
The execution of the insert is the same as if you had relied on the metadata to determine which columns to use.
19.5.4 Using SqlParameterSource to provide parameter values
Using a Map
to provide parameter values works fine, but it’s not the most convenient class to use. Spring provides a couple of implementations of theSqlParameterSource
interface that can be used instead.The first one is BeanPropertySqlParameterSource
, which is a very convenient class if you have a JavaBean-compliant class that contains your values. It will use the corresponding getter method to extract the parameter values. Here is an example:
public class JdbcActorDao implements ActorDao { private JdbcTemplate jdbcTemplate; private SimpleJdbcInsert insertActor; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); this.insertActor = new SimpleJdbcInsert(dataSource) .withTableName("t_actor") .usingGeneratedKeyColumns("id"); } public void add(Actor actor) { SqlParameterSource parameters = new BeanPropertySqlParameterSource(actor); Number newId = insertActor.executeAndReturnKey(parameters); actor.setId(newId.longValue()); } // ... additional methods }
Another option is the MapSqlParameterSource
that resembles a Map but provides a more convenient addValue
method that can be chained.
public class JdbcActorDao implements ActorDao { private JdbcTemplate jdbcTemplate; private SimpleJdbcInsert insertActor; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); this.insertActor = new SimpleJdbcInsert(dataSource) .withTableName("t_actor") .usingGeneratedKeyColumns("id"); } public void add(Actor actor) { SqlParameterSource parameters = new MapSqlParameterSource() .addValue("first_name", actor.getFirstName()) .addValue("last_name", actor.getLastName()); Number newId = insertActor.executeAndReturnKey(parameters); actor.setId(newId.longValue()); } // ... additional methods }
As you can see, the configuration is the same; only the executing code has to change to use these alternative input classes.
19.5.5 Calling a stored procedure with SimpleJdbcCall
The SimpleJdbcCall
class leverages metadata in the database to look up names of in
and out
parameters, so that you do not have to declare them explicitly. You can declare parameters if you prefer to do that, or if you have parameters such as ARRAY
or STRUCT
that do not have an automatic mapping to a Java class. The first example shows a simple procedure that returns only scalar values in VARCHAR
and DATE
format from a MySQL database. The example procedure reads a specified actor entry and returns first_name
, last_name
, and birth_date
columns in the form of out
parameters.
CREATE PROCEDURE read_actor ( IN in_id INTEGER, OUT out_first_name VARCHAR(100), OUT out_last_name VARCHAR(100), OUT out_birth_date DATE) BEGIN SELECT first_name, last_name, birth_date INTO out_first_name, out_last_name, out_birth_date FROM t_actor where id = in_id; END;
The in_id
parameter contains the id
of the actor you are looking up. The out
parameters return the data read from the table.
The SimpleJdbcCall
is declared in a similar manner to the SimpleJdbcInsert
. You should instantiate and configure the class in the initialization method of your data access layer. Compared to the StoredProcedure class, you don’t have to create a subclass and you don’t have to declare parameters that can be looked up in the database metadata. Following is an example of a SimpleJdbcCall configuration using the above stored procedure. The only configuration option, in addition to the DataSource
, is the name of the stored procedure.
public class JdbcActorDao implements ActorDao { private JdbcTemplate jdbcTemplate; private SimpleJdbcCall procReadActor; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); this.procReadActor = new SimpleJdbcCall(dataSource) .withProcedureName("read_actor"); } public Actor readActor(Long id) { SqlParameterSource in = new MapSqlParameterSource() .addValue("in_id", id); Map out = procReadActor.execute(in); Actor actor = new Actor(); actor.setId(id); actor.setFirstName((String) out.get("out_first_name")); actor.setLastName((String) out.get("out_last_name")); actor.setBirthDate((Date) out.get("out_birth_date")); return actor; } // ... additional methods }
The code you write for the execution of the call involves creating an SqlParameterSource
containing the IN parameter. It’s important to match the name provided for the input value with that of the parameter name declared in the stored procedure. The case does not have to match because you use metadata to determine how database objects should be referred to in a stored procedure. What is specified in the source for the stored procedure is not necessarily the way it is stored in the database. Some databases transform names to all upper case while others use lower case or use the case as specified.
The execute
method takes the IN parameters and returns a Map containing any out
parameters keyed by the name as specified in the stored procedure. In this case they are out_first_name, out_last_name
and out_birth_date
.
The last part of the execute
method creates an Actor instance to use to return the data retrieved. Again, it is important to use the names of the out
parameters as they are declared in the stored procedure. Also, the case in the names of the out
parameters stored in the results map matches that of the out
parameter names in the database, which could vary between databases. To make your code more portable you should do a case-insensitive lookup or instruct Spring to use a LinkedCaseInsensitiveMap
. To do the latter, you create your own JdbcTemplate
and set the setResultsMapCaseInsensitive
property to true
. Then you pass this customized JdbcTemplate
instance into the constructor of your SimpleJdbcCall
. Here is an example of this configuration:
public class JdbcActorDao implements ActorDao { private SimpleJdbcCall procReadActor; public void setDataSource(DataSource dataSource) { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); jdbcTemplate.setResultsMapCaseInsensitive(true); this.procReadActor = new SimpleJdbcCall(jdbcTemplate) .withProcedureName("read_actor"); } // ... additional methods }
By taking this action, you avoid conflicts in the case used for the names of your returned out
parameters.
19.5.6 Explicitly declaring parameters to use for a SimpleJdbcCall
You have seen how the parameters are deduced based on metadata, but you can declare then explicitly if you wish. You do this by creating and configuringSimpleJdbcCall
with the declareParameters
method, which takes a variable number of SqlParameter
objects as input. See the next section for details on how to define an SqlParameter
.
Explicit declarations are necessary if the database you use is not a Spring-supported database. Currently Spring supports metadata lookup of stored procedure calls for the following databases: Apache Derby, DB2, MySQL, Microsoft SQL Server, Oracle, and Sybase. We also support metadata lookup of stored functions for MySQL, Microsoft SQL Server, and Oracle. |
You can opt to declare one, some, or all the parameters explicitly. The parameter metadata is still used where you do not declare parameters explicitly. To bypass all processing of metadata lookups for potential parameters and only use the declared parameters, you call the methodwithoutProcedureColumnMetaDataAccess
as part of the declaration. Suppose that you have two or more different call signatures declared for a database function. In this case you call the useInParameterNames
to specify the list of IN parameter names to include for a given signature.
The following example shows a fully declared procedure call, using the information from the preceding example.
public class JdbcActorDao implements ActorDao { private SimpleJdbcCall procReadActor; public void setDataSource(DataSource dataSource) { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); jdbcTemplate.setResultsMapCaseInsensitive(true); this.procReadActor = new SimpleJdbcCall(jdbcTemplate) .withProcedureName("read_actor") .withoutProcedureColumnMetaDataAccess() .useInParameterNames("in_id") .declareParameters( new SqlParameter("in_id", Types.NUMERIC), new SqlOutParameter("out_first_name", Types.VARCHAR), new SqlOutParameter("out_last_name", Types.VARCHAR), new SqlOutParameter("out_birth_date", Types.DATE) ); } // ... additional methods }
The execution and end results of the two examples are the same; this one specifies all details explicitly rather than relying on metadata.
19.5.7 How to define SqlParameters
To define a parameter for the SimpleJdbc classes and also for the RDBMS operations classes, covered in Section 19.6, “Modeling JDBC operations as Java objects”, you use an SqlParameter
or one of its subclasses. You typically specify the parameter name and SQL type in the constructor. The SQL type is specified using the java.sql.Types
constants. We have already seen declarations like:
new SqlParameter("in_id", Types.NUMERIC), new SqlOutParameter("out_first_name", Types.VARCHAR),
The first line with the SqlParameter
declares an IN parameter. IN parameters can be used for both stored procedure calls and for queries using theSqlQuery
and its subclasses covered in the following section.
The second line with the SqlOutParameter
declares an out
parameter to be used in a stored procedure call. There is also an SqlInOutParameter
forInOut
parameters, parameters that provide an IN
value to the procedure and that also return a value.
Only parameters declared as |
For IN parameters, in addition to the name and the SQL type, you can specify a scale for numeric data or a type name for custom database types. For out
parameters, you can provide a RowMapper
to handle mapping of rows returned from a REF
cursor. Another option is to specify an SqlReturnType
that provides an opportunity to define customized handling of the return values.
19.5.8 Calling a stored function using SimpleJdbcCall
You call a stored function in almost the same way as you call a stored procedure, except that you provide a function name rather than a procedure name. You use the withFunctionName
method as part of the configuration to indicate that we want to make a call to a function, and the corresponding string for a function call is generated. A specialized execute call, executeFunction,
is used to execute the function and it returns the function return value as an object of a specified type, which means you do not have to retrieve the return value from the results map. A similar convenience method named executeObject
is also available for stored procedures that only have one out
parameter. The following example is based on a stored function named get_actor_name
that returns an actor’s full name. Here is the MySQL source for this function:
CREATE FUNCTION get_actor_name (in_id INTEGER) RETURNS VARCHAR(200) READS SQL DATA BEGIN DECLARE out_name VARCHAR(200); SELECT concat(first_name, ' ', last_name) INTO out_name FROM t_actor where id = in_id; RETURN out_name; END;
To call this function we again create a SimpleJdbcCall
in the initialization method.
public class JdbcActorDao implements ActorDao { private JdbcTemplate jdbcTemplate; private SimpleJdbcCall funcGetActorName; public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); jdbcTemplate.setResultsMapCaseInsensitive(true); this.funcGetActorName = new SimpleJdbcCall(jdbcTemplate) .withFunctionName("get_actor_name"); } public String getActorName(Long id) { SqlParameterSource in = new MapSqlParameterSource() .addValue("in_id", id); String name = funcGetActorName.executeFunction(String.class, in); return name; } // ... additional methods }
The execute method used returns a String
containing the return value from the function call.
19.5.9 Returning ResultSet/REF Cursor from a SimpleJdbcCall
Calling a stored procedure or function that returns a result set is a bit tricky. Some databases return result sets during the JDBC results processing while others require an explicitly registered out
parameter of a specific type. Both approaches need additional processing to loop over the result set and process the returned rows. With the SimpleJdbcCall
you use the returningResultSet
method and declare a RowMapper
implementation to be used for a specific parameter. In the case where the result set is returned during the results processing, there are no names defined, so the returned results will have to match the order in which you declare the RowMapper
implementations. The name specified is still used to store the processed list of results in the results map that is returned from the execute statement.
The next example uses a stored procedure that takes no IN parameters and returns all rows from the t_actor table. Here is the MySQL source for this procedure:
CREATE PROCEDURE read_all_actors() BEGIN SELECT a.id, a.first_name, a.last_name, a.birth_date FROM t_actor a; END;
To call this procedure you declare the RowMapper
. Because the class you want to map to follows the JavaBean rules, you can use aBeanPropertyRowMapper
that is created by passing in the required class to map to in the newInstance
method.
public class JdbcActorDao implements ActorDao { private SimpleJdbcCall procReadAllActors; public void setDataSource(DataSource dataSource) { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); jdbcTemplate.setResultsMapCaseInsensitive(true); this.procReadAllActors = new SimpleJdbcCall(jdbcTemplate) .withProcedureName("read_all_actors") .returningResultSet("actors", BeanPropertyRowMapper.newInstance(Actor.class)); } public List getActorsList() { Map m = procReadAllActors.execute(new HashMap<String, Object>(0)); return (List) m.get("actors"); } // ... additional methods }
The execute call passes in an empty Map because this call does not take any parameters. The list of Actors is then retrieved from the results map and returned to the caller.
19.6 Modeling JDBC operations as Java objects
The org.springframework.jdbc.object
package contains classes that allow you to access the database in a more object-oriented manner. As an example, you can execute queries and get the results back as a list containing business objects with the relational column data mapped to the properties of the business object. You can also execute stored procedures and run update, delete, and insert statements.
Many Spring developers believe that the various RDBMS operation classes described below (with the exception of the However, if you are getting measurable value from using the RDBMS operation classes, continue using these classes. |
19.6.1 SqlQuery
SqlQuery
is a reusable, threadsafe class that encapsulates an SQL query. Subclasses must implement the newRowMapper(..)
method to provide aRowMapper
instance that can create one object per row obtained from iterating over the ResultSet
that is created during the execution of the query. TheSqlQuery
class is rarely used directly because the MappingSqlQuery
subclass provides a much more convenient implementation for mapping rows to Java classes. Other implementations that extend SqlQuery
are MappingSqlQueryWithParameters
and UpdatableSqlQuery
.
19.6.2 MappingSqlQuery
MappingSqlQuery
is a reusable query in which concrete subclasses must implement the abstract mapRow(..)
method to convert each row of the suppliedResultSet
into an object of the type specified. The following example shows a custom query that maps the data from the t_actor
relation to an instance of the Actor
class.
public class ActorMappingQuery extends MappingSqlQuery<Actor> { public ActorMappingQuery(DataSource ds) { super(ds, "select id, first_name, last_name from t_actor where id = ?"); super.declareParameter(new SqlParameter("id", Types.INTEGER)); compile(); } @Override protected Actor mapRow(ResultSet rs, int rowNumber) throws SQLException { Actor actor = new Actor(); actor.setId(rs.getLong("id")); actor.setFirstName(rs.getString("first_name")); actor.setLastName(rs.getString("last_name")); return actor; } }
The class extends MappingSqlQuery
parameterized with the Actor
type. The constructor for this customer query takes the DataSource
as the only parameter. In this constructor you call the constructor on the superclass with the DataSource
and the SQL that should be executed to retrieve the rows for this query. This SQL will be used to create a PreparedStatement
so it may contain place holders for any parameters to be passed in during execution.You must declare each parameter using the declareParameter
method passing in an SqlParameter
. The SqlParameter
takes a name and the JDBC type as defined in java.sql.Types
. After you define all parameters, you call the compile()
method so the statement can be prepared and later executed. This class is thread-safe after it is compiled, so as long as these instances are created when the DAO is initialized they can be kept as instance variables and be reused.
private ActorMappingQuery actorMappingQuery; @Autowired public void setDataSource(DataSource dataSource) { this.actorMappingQuery = new ActorMappingQuery(dataSource); } public Customer getCustomer(Long id) { return actorMappingQuery.findObject(id); }
The method in this example retrieves the customer with the id that is passed in as the only parameter. Since we only want one object returned we simply call the convenience method findObject
with the id as parameter. If we had instead a query that returned a list of objects and took additional parameters then we would use one of the execute methods that takes an array of parameter values passed in as varargs.
public List<Actor> searchForActors(int age, String namePattern) { List<Actor> actors = actorSearchMappingQuery.execute(age, namePattern); return actors; }
19.6.3 SqlUpdate
The SqlUpdate
class encapsulates an SQL update. Like a query, an update object is reusable, and like all RdbmsOperation
classes, an update can have parameters and is defined in SQL. This class provides a number of update(..)
methods analogous to the execute(..)
methods of query objects. TheSQLUpdate
class is concrete. It can be subclassed, for example, to add a custom update method, as in the following snippet where it’s simply called execute
. However, you don’t have to subclass the SqlUpdate
class since it can easily be parameterized by setting SQL and declaring parameters.
import java.sql.Types; import javax.sql.DataSource; import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.object.SqlUpdate; public class UpdateCreditRating extends SqlUpdate { public UpdateCreditRating(DataSource ds) { setDataSource(ds); setSql("update customer set credit_rating = ? where id = ?"); declareParameter(new SqlParameter("creditRating", Types.NUMERIC)); declareParameter(new SqlParameter("id", Types.NUMERIC)); compile(); } /** * @param id for the Customer to be updated * @param rating the new value for credit rating * @return number of rows updated */ public int execute(int id, int rating) { return update(rating, id); } }
19.6.4 StoredProcedure
The StoredProcedure
class is a superclass for object abstractions of RDBMS stored procedures. This class is abstract
, and its various execute(..)
methods have protected
access, preventing use other than through a subclass that offers tighter typing.
The inherited sql
property will be the name of the stored procedure in the RDBMS.
To define a parameter for the StoredProcedure
class, you use an SqlParameter
or one of its subclasses. You must specify the parameter name and SQL type in the constructor like in the following code snippet. The SQL type is specified using the java.sql.Types
constants.
new SqlParameter("in_id", Types.NUMERIC), new SqlOutParameter("out_first_name", Types.VARCHAR),
The first line with the SqlParameter
declares an IN parameter. IN parameters can be used for both stored procedure calls and for queries using theSqlQuery
and its subclasses covered in the following section.
The second line with the SqlOutParameter
declares an out
parameter to be used in the stored procedure call. There is also an SqlInOutParameter
for I
nOut
parameters, parameters that provide an in
value to the procedure and that also return a value.
For i
n
parameters, in addition to the name and the SQL type, you can specify a scale for numeric data or a type name for custom database types. For out
parameters you can provide a RowMapper
to handle mapping of rows returned from a REF cursor. Another option is to specify an SqlReturnType
that enables you to define customized handling of the return values.
Here is an example of a simple DAO that uses a StoredProcedure
to call a function, sysdate()
,which comes with any Oracle database. To use the stored procedure functionality you have to create a class that extends StoredProcedure
. In this example, the StoredProcedure
class is an inner class, but if you need to reuse the StoredProcedure
you declare it as a top-level class. This example has no input parameters, but an output parameter is declared as a date type using the class SqlOutParameter
. The execute()
method executes the procedure and extracts the returned date from the results Map
. The resultsMap
has an entry for each declared output parameter, in this case only one, using the parameter name as the key.
import java.sql.Types; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.SqlOutParameter; import org.springframework.jdbc.object.StoredProcedure; public class StoredProcedureDao { private GetSysdateProcedure getSysdate; @Autowired public void init(DataSource dataSource) { this.getSysdate = new GetSysdateProcedure(dataSource); } public Date getSysdate() { return getSysdate.execute(); } private class GetSysdateProcedure extends StoredProcedure { private static final String SQL = "sysdate"; public GetSysdateProcedure(DataSource dataSource) { setDataSource(dataSource); setFunction(true); setSql(SQL); declareParameter(new SqlOutParameter("date", Types.DATE)); compile(); } public Date execute() { // the 'sysdate' sproc has no input parameters, so an empty Map is supplied... Map<String, Object> results = execute(new HashMap<String, Object>()); Date sysdate = (Date) results.get("date"); return sysdate; } } }
The following example of a StoredProcedure
has two output parameters (in this case, Oracle REF cursors).
import oracle.jdbc.OracleTypes; import org.springframework.jdbc.core.SqlOutParameter; import org.springframework.jdbc.object.StoredProcedure; import javax.sql.DataSource; import java.util.HashMap; import java.util.Map; public class TitlesAndGenresStoredProcedure extends StoredProcedure { private static final String SPROC_NAME = "AllTitlesAndGenres"; public TitlesAndGenresStoredProcedure(DataSource dataSource) { super(dataSource, SPROC_NAME); declareParameter(new SqlOutParameter("titles", OracleTypes.CURSOR, new TitleMapper())); declareParameter(new SqlOutParameter("genres", OracleTypes.CURSOR, new GenreMapper())); compile(); } public Map<String, Object> execute() { // again, this sproc has no input parameters, so an empty Map is supplied return super.execute(new HashMap<String, Object>()); } }
Notice how the overloaded variants of the declareParameter(..)
method that have been used in the TitlesAndGenresStoredProcedure
constructor are passed RowMapper
implementation instances; this is a very convenient and powerful way to reuse existing functionality. The code for the two RowMapper
implementations is provided below.
The TitleMapper
class maps a ResultSet
to a Title
domain object for each row in the supplied ResultSet
:
import org.springframework.jdbc.core.RowMapper; import java.sql.ResultSet; import java.sql.SQLException; import com.foo.domain.Title; public final class TitleMapper implements RowMapper<Title> { public Title mapRow(ResultSet rs, int rowNum) throws SQLException { Title title = new Title(); title.setId(rs.getLong("id")); title.setName(rs.getString("name")); return title; } }
The GenreMapper
class maps a ResultSet
to a Genre
domain object for each row in the supplied ResultSet
.
import org.springframework.jdbc.core.RowMapper; import java.sql.ResultSet; import java.sql.SQLException; import com.foo.domain.Genre; public final class GenreMapper implements RowMapper<Genre> { public Genre mapRow(ResultSet rs, int rowNum) throws SQLException { return new Genre(rs.getString("name")); } }
To pass parameters to a stored procedure that has one or more input parameters in its definition in the RDBMS, you can code a strongly typed execute(..)
method that would delegate to the superclass' untyped execute(Map parameters)
method (which has protected
access); for example:
import oracle.jdbc.OracleTypes; import org.springframework.jdbc.core.SqlOutParameter; import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.object.StoredProcedure; import javax.sql.DataSource; import java.sql.Types; import java.util.Date; import java.util.HashMap; import java.util.Map; public class TitlesAfterDateStoredProcedure extends StoredProcedure { private static final String SPROC_NAME = "TitlesAfterDate"; private static final String CUTOFF_DATE_PARAM = "cutoffDate"; public TitlesAfterDateStoredProcedure(DataSource dataSource) { super(dataSource, SPROC_NAME); declareParameter(new SqlParameter(CUTOFF_DATE_PARAM, Types.DATE); declareParameter(new SqlOutParameter("titles", OracleTypes.CURSOR, new TitleMapper())); compile(); } public Map<String, Object> execute(Date cutoffDate) { Map<String, Object> inputs = new HashMap<String, Object>(); inputs.put(CUTOFF_DATE_PARAM, cutoffDate); return super.execute(inputs); } }
19.7 Common problems with parameter and data value handling
Common problems with parameters and data values exist in the different approaches provided by the Spring Framework JDBC.
19.7.1 Providing SQL type information for parameters
Usually Spring determines the SQL type of the parameters based on the type of parameter passed in. It is possible to explicitly provide the SQL type to be used when setting parameter values. This is sometimes necessary to correctly set NULL values.
You can provide SQL type information in several ways:
- Many update and query methods of the
JdbcTemplate
take an additional parameter in the form of anint
array. This array is used to indicate the SQL type of the corresponding parameter using constant values from thejava.sql.Types
class. Provide one entry for each parameter. - You can use the
SqlParameterValue
class to wrap the parameter value that needs this additional information.Create a new instance for each value and pass in the SQL type and parameter value in the constructor. You can also provide an optional scale parameter for numeric values. - For methods working with named parameters, use the
SqlParameterSource
classesBeanPropertySqlParameterSource
orMapSqlParameterSource
. They both have methods for registering the SQL type for any of the named parameter values.
19.7.2 Handling BLOB and CLOB objects
You can store images, other binary data, and large chunks of text in the database. These large objects are called BLOBs (Binary Large OBject) for binary data and CLOBs (Character Large OBject) for character data. In Spring you can handle these large objects by using the JdbcTemplate
directly and also when using the higher abstractions provided by RDBMS Objects and the SimpleJdbc
classes. All of these approaches use an implementation of the LobHandler
interface for the actual management of the LOB (Large OBject) data. The LobHandler
provides access to a LobCreator
class, through the getLobCreator
method, used for creating new LOB objects to be inserted.
The LobCreator/LobHandler
provides the following support for LOB input and output:
BLOB
byte[]
—getBlobAsBytes
andsetBlobAsBytes
InputStream
—getBlobAsBinaryStream
andsetBlobAsBinaryStream
CLOB
String
—getClobAsString
andsetClobAsString
InputStream
—getClobAsAsciiStream
andsetClobAsAsciiStream
Reader
—getClobAsCharacterStream
andsetClobAsCharacterStream
The next example shows how to create and insert a BLOB. Later you will see how to read it back from the database.
This example uses a JdbcTemplate
and an implementation of the AbstractLobCreatingPreparedStatementCallback
. It implements one method,setValues
. This method provides a LobCreator
that you use to set the values for the LOB columns in your SQL insert statement.
For this example we assume that there is a variable, lobHandler
, that already is set to an instance of a DefaultLobHandler
. You typically set this value through dependency injection.
final File blobIn = new File("spring2004.jpg"); final InputStream blobIs = new FileInputStream(blobIn); final File clobIn = new File("large.txt"); final InputStream clobIs = new FileInputStream(clobIn); final InputStreamReader clobReader = new InputStreamReader(clobIs); jdbcTemplate.execute( "INSERT INTO lob_table (id, a_clob, a_blob) VALUES (?, ?, ?)", new AbstractLobCreatingPreparedStatementCallback(lobHandler) { protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException { ps.setLong(1, 1L); lobCreator.setClobAsCharacterStream(ps, 2, clobReader, (int)clobIn.length()); lobCreator.setBlobAsBinaryStream(ps, 3, blobIs, (int)blobIn.length()); } } ); blobIs.close(); clobReader.close();
Pass in the | |
Using the method | |
Using the method |
If you invoke the Consult the documentation for the JDBC driver in use to verify support for streaming a LOB without providing the content length. |
Now it’s time to read the LOB data from the database. Again, you use a JdbcTemplate
with the same instance variable lobHandler
and a reference to aDefaultLobHandler
.
List<Map<String, Object>> l = jdbcTemplate.query("select id, a_clob, a_blob from lob_table", new RowMapper<Map<String, Object>>() { public Map<String, Object> mapRow(ResultSet rs, int i) throws SQLException { Map<String, Object> results = new HashMap<String, Object>(); String clobText = lobHandler.getClobAsString(rs, "a_clob"); results.put("CLOB", clobText); byte[] blobBytes = lobHandler.getBlobAsBytes(rs, "a_blob"); results.put("BLOB", blobBytes); return results; } });
19.7.3 Passing in lists of values for IN clause
The SQL standard allows for selecting rows based on an expression that includes a variable list of values. A typical example would beselect * from T_ACTOR where id in (1, 2, 3)
. This variable list is not directly supported for prepared statements by the JDBC standard; you cannot declare a variable number of placeholders. You need a number of variations with the desired number of placeholders prepared, or you need to generate the SQL string dynamically once you know how many placeholders are required. The named parameter support provided in the NamedParameterJdbcTemplate
and JdbcTemplate
takes the latter approach. Pass in the values as a java.util.List
of primitive objects. This list will be used to insert the required placeholders and pass in the values during the statement execution.
Be careful when passing in many values. The JDBC standard does not guarantee that you can use more than 100 values for an |
In addition to the primitive values in the value list, you can create a java.util.List
of object arrays. This list would support multiple expressions defined for the in
clause such as select * from T_ACTOR where (id, last_name) in 1, 'Johnson'), (2, 'Harrop'
. This of course requires that your database supports this syntax.
19.7.4 Handling complex types for stored procedure calls
When you call stored procedures you can sometimes use complex types specific to the database. To accommodate these types, Spring provides aSqlReturnType
for handling them when they are returned from the stored procedure call and SqlTypeValue
when they are passed in as a parameter to the stored procedure.
Here is an example of returning the value of an Oracle STRUCT
object of the user declared type ITEM_TYPE
. The SqlReturnType
interface has a single method named getTypeValue
that must be implemented. This interface is used as part of the declaration of an SqlOutParameter
.
final TestItem = new TestItem(123L, "A test item", new SimpleDateFormat("yyyy-M-d").parse("2010-12-31")); declareParameter(new SqlOutParameter("item", OracleTypes.STRUCT, "ITEM_TYPE", new SqlReturnType() { public Object getTypeValue(CallableStatement cs, int colIndx, int sqlType, String typeName) throws SQLException { STRUCT struct = (STRUCT) cs.getObject(colIndx); Object[] attr = struct.getAttributes(); TestItem item = new TestItem(); item.setId(((Number) attr[0]).longValue()); item.setDescription((String) attr[1]); item.setExpirationDate((java.util.Date) attr[2]); return item; } }));
You use the SqlTypeValue
to pass in the value of a Java object like TestItem
into a stored procedure. The SqlTypeValue
interface has a single method named createTypeValue
that you must implement. The active connection is passed in, and you can use it to create database-specific objects such asStructDescriptor
s, as shown in the following example, or ArrayDescriptor
s.
final TestItem = new TestItem(123L, "A test item", new SimpleDateFormat("yyyy-M-d").parse("2010-12-31")); SqlTypeValue value = new AbstractSqlTypeValue() { protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException { StructDescriptor itemDescriptor = new StructDescriptor(typeName, conn); Struct item = new STRUCT(itemDescriptor, conn, new Object[] { testItem.getId(), testItem.getDescription(), new java.sql.Date(testItem.getExpirationDate().getTime()) }); return item; } };
This SqlTypeValue
can now be added to the Map containing the input parameters for the execute call of the stored procedure.
Another use for the SqlTypeValue
is passing in an array of values to an Oracle stored procedure. Oracle has its own internal ARRAY
class that must be used in this case, and you can use the SqlTypeValue
to create an instance of the Oracle ARRAY
and populate it with values from the Java ARRAY
.
final Long[] ids = new Long[] {1L, 2L}; SqlTypeValue value = new AbstractSqlTypeValue() { protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException { ArrayDescriptor arrayDescriptor = new ArrayDescriptor(typeName, conn); ARRAY idArray = new ARRAY(arrayDescriptor, conn, ids); return idArray; } };
19.8 Embedded database support
The org.springframework.jdbc.datasource.embedded
package provides support for embedded Java database engines. Support for HSQL, H2, andDerby is provided natively. You can also use an extensible API to plug in new embedded database types and DataSource
implementations.
19.8.1 Why use an embedded database?
An embedded database is useful during the development phase of a project because of its lightweight nature. Benefits include ease of configuration, quick startup time, testability, and the ability to rapidly evolve SQL during development.
19.8.2 Creating an embedded database using Spring XML
If you want to expose an embedded database instance as a bean in a Spring ApplicationContext
, use the embedded-database
tag in the spring-jdbc
namespace:
<jdbc:embedded-database id="dataSource" generate-name="true"> <jdbc:script location="classpath:schema.sql"/> <jdbc:script location="classpath:test-data.sql"/> </jdbc:embedded-database>
The preceding configuration creates an embedded HSQL database populated with SQL from schema.sql
and test-data.sql
resources in the root of the classpath. In addition, as a best practice, the embedded database will be assigned a uniquely generated name. The embedded database is made available to the Spring container as a bean of type javax.sql.DataSource
which can then be injected into data access objects as needed.
19.8.3 Creating an embedded database programmatically
The EmbeddedDatabaseBuilder
class provides a fluent API for constructing an embedded database programmatically. Use this when you need to create an embedded database in a standalone environment or in a standalone integration test like in the following example.
EmbeddedDatabase db = new EmbeddedDatabaseBuilder() .generateUniqueName(true) .setType(H2) .setScriptEncoding("UTF-8") .ignoreFailedDrops(true) .addScript("schema.sql") .addScripts("user_data.sql", "country_data.sql") .build(); // perform actions against the db (EmbeddedDatabase extends javax.sql.DataSource) db.shutdown()
Consult the Javadoc for EmbeddedDatabaseBuilder
for further details on all supported options.
The EmbeddedDatabaseBuilder
can also be used to create an embedded database using Java Config like in the following example.
@Configuration public class DataSourceConfig { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .generateUniqueName(true) .setType(H2) .setScriptEncoding("UTF-8") .ignoreFailedDrops(true) .addScript("schema.sql") .addScripts("user_data.sql", "country_data.sql") .build(); } }
19.8.4 Selecting the embedded database type
Using HSQL
Spring supports HSQL 1.8.0 and above. HSQL is the default embedded database if no type is specified explicitly. To specify HSQL explicitly, set the type
attribute of the embedded-database
tag to HSQL
. If you are using the builder API, call the setType(EmbeddedDatabaseType)
method withEmbeddedDatabaseType.HSQL
.
Using H2
Spring supports the H2 database as well. To enable H2, set the type
attribute of the embedded-database
tag to H2
. If you are using the builder API, call thesetType(EmbeddedDatabaseType)
method with EmbeddedDatabaseType.H2
.
Using Derby
Spring also supports Apache Derby 10.5 and above. To enable Derby, set the type
attribute of the embedded-database
tag to DERBY
. If you are using the builder API, call the setType(EmbeddedDatabaseType)
method with EmbeddedDatabaseType.DERBY
.
19.8.5 Testing data access logic with an embedded database
Embedded databases provide a lightweight way to test data access code. The following is a data access integration test template that uses an embedded database. Using a template like this can be useful for one-offs when the embedded database does not need to be reused across test classes. However, if you wish to create an embedded database that is shared within a test suite, consider using the Spring TestContext Framework and configuring the embedded database as a bean in the Spring ApplicationContext
as described in Section 19.8.2, “Creating an embedded database using Spring XML” andSection 19.8.3, “Creating an embedded database programmatically”.
public class DataAccessIntegrationTestTemplate { private EmbeddedDatabase db; @Before public void setUp() { // creates an HSQL in-memory database populated from default scripts // classpath:schema.sql and classpath:data.sql db = new EmbeddedDatabaseBuilder() .generateUniqueName(true) .addDefaultScripts() .build(); } @Test public void testDataAccess() { JdbcTemplate template = new JdbcTemplate(db); template.query( /* ... */ ); } @After public void tearDown() { db.shutdown(); } }
19.8.6 Generating unique names for embedded databases
Development teams often encounter errors with embedded databases if their test suite inadvertently attempts to recreate additional instances of the same database. This can happen quite easily if an XML configuration file or @Configuration
class is responsible for creating an embedded database and the corresponding configuration is then reused across multiple testing scenarios within the same test suite (i.e., within the same JVM process) –- for example, integration tests against embedded databases whose ApplicationContext
configuration only differs with regard to which bean definition profiles are active.
The root cause of such errors is the fact that Spring’s EmbeddedDatabaseFactory
(used internally by both the <jdbc:embedded-database>
XML namespace element and the EmbeddedDatabaseBuilder
for Java Config) will set the name of the embedded database to "testdb"
if not otherwise specified. For the case of <jdbc:embedded-database>
, the embedded database is typically assigned a name equal to the bean’s id
(i.e., often something like "dataSource"
). Thus, subsequent attempts to create an embedded database will not result in a new database. Instead, the same JDBC connection URL will be reused, and attempts to create a new embedded database will actually point to an existing embedded database created from the same configuration.
To address this common issue Spring Framework 4.2 provides support for generating unique names for embedded databases. To enable the use of generated names, use one of the following options.
EmbeddedDatabaseFactory.setGenerateUniqueDatabaseName()
EmbeddedDatabaseBuilder.generateUniqueName()
<jdbc:embedded-database generate-name="true" … >
19.8.7 Extending the embedded database support
Spring JDBC embedded database support can be extended in two ways:
- Implement
EmbeddedDatabaseConfigurer
to support a new embedded database type. - Implement
DataSourceFactory
to support a newDataSource
implementation, such as a connection pool to manage embedded database connections.
You are encouraged to contribute back extensions to the Spring community at jira.spring.io.
19.9 Initializing a DataSource
The org.springframework.jdbc.datasource.init
package provides support for initializing an existing DataSource
. The embedded database support provides one option for creating and initializing a DataSource
for an application, but sometimes you need to initialize an instance running on a server somewhere.
19.9.1 Initializing a database using Spring XML
If you want to initialize a database and you can provide a reference to a DataSource
bean, use the initialize-database
tag in the spring-jdbc
namespace:
<jdbc:initialize-database data-source="dataSource"> <jdbc:script location="classpath:com/foo/sql/db-schema.sql"/> <jdbc:script location="classpath:com/foo/sql/db-test-data.sql"/> </jdbc:initialize-database>
The example above executes the two scripts specified against the database: the first script creates a schema, and the second populates tables with a test data set. The script locations can also be patterns with wildcards in the usual ant style used for resources in Spring (e.g.classpath*:/com/foo/**/sql/*-data.sql
). If a pattern is used, the scripts are executed in lexical order of their URL or filename.
The default behavior of the database initializer is to unconditionally execute the scripts provided. This will not always be what you want, for instance, if you are executing the scripts against a database that already has test data in it. The likelihood of accidentally deleting data is reduced by following the common pattern (as shown above) of creating the tables first and then inserting the data — the first step will fail if the tables already exist.
However, to gain more control over the creation and deletion of existing data, the XML namespace provides a few additional options. The first is a flag to switch the initialization on and off. This can be set according to the environment (e.g. to pull a boolean value from system properties or an environment bean), for example:
<jdbc:initialize-database data-source="dataSource" enabled="#{systemProperties.INITIALIZE_DATABASE}"> <jdbc:script location="..."/> </jdbc:initialize-database>
The second option to control what happens with existing data is to be more tolerant of failures. To this end you can control the ability of the initializer to ignore certain errors in the SQL it executes from the scripts, for example:
<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS"> <jdbc:script location="..."/> </jdbc:initialize-database>
In this example we are saying we expect that sometimes the scripts will be executed against an empty database, and there are some DROP
statements in the scripts which would therefore fail. So failed SQL DROP
statements will be ignored, but other failures will cause an exception. This is useful if your SQL dialect doesn’t support DROP … IF EXISTS
(or similar) but you want to unconditionally remove all test data before re-creating it. In that case the first script is usually a set of DROP
statements, followed by a set of CREATE
statements.
The ignore-failures
option can be set to NONE
(the default), DROPS
(ignore failed drops), or ALL
(ignore all failures).
Each statement should be separated by ;
or a new line if the ;
character is not present at all in the script. You can control that globally or script by script, for example:
<jdbc:initialize-database data-source="dataSource" separator="@@"> <jdbc:script location="classpath:com/foo/sql/db-schema.sql" separator=";"/> <jdbc:script location="classpath:com/foo/sql/db-test-data-1.sql"/> <jdbc:script location="classpath:com/foo/sql/db-test-data-2.sql"/> </jdbc:initialize-database>
In this example, the two test-data
scripts use @@
as statement separator and only the db-schema.sql
uses ;
. This configuration specifies that the default separator is @@
and override that default for the db-schema
script.
If you need more control than you get from the XML namespace, you can simply use the DataSourceInitializer
directly and define it as a component in your application.
Initialization of other components that depend on the database
A large class of applications can just use the database initializer with no further complications: those that do not use the database until after the Spring context has started. If your application is not one of those then you might need to read the rest of this section.
The database initializer depends on a DataSource
instance and executes the scripts provided in its initialization callback (analogous to an init-method
in an XML bean definition, a @PostConstruct
method in a component, or the afterPropertiesSet()
method in a component that implementsInitializingBean
). If other beans depend on the same data source and also use the data source in an initialization callback, then there might be a problem because the data has not yet been initialized. A common example of this is a cache that initializes eagerly and loads data from the database on application startup.
To get around this issue you have two options: change your cache initialization strategy to a later phase, or ensure that the database initializer is initialized first.
The first option might be easy if the application is in your control, and not otherwise. Some suggestions for how to implement this include:
- Make the cache initialize lazily on first usage, which improves application startup time.
- Have your cache or a separate component that initializes the cache implement
Lifecycle
orSmartLifecycle
. When the application context starts up aSmartLifecycle
can be automatically started if itsautoStartup
flag is set, and aLifecycle
can be started manually by callingConfigurableApplicationContext.start()
on the enclosing context. - Use a Spring
ApplicationEvent
or similar custom observer mechanism to trigger the cache initialization.ContextRefreshedEvent
is always published by the context when it is ready for use (after all beans have been initialized), so that is often a useful hook (this is how theSmartLifecycle
works by default).
The second option can also be easy. Some suggestions on how to implement this include:
- Rely on the default behavior of the Spring
BeanFactory
, which is that beans are initialized in registration order. You can easily arrange that by adopting the common practice of a set of<import/>
elements in XML configuration that order your application modules, and ensure that the database and database initialization are listed first. - Separate the
DataSource
and the business components that use it, and control their startup order by putting them in separateApplicationContext
instances (e.g. the parent context contains theDataSource
, and child context contains the business components). This structure is common in Spring web applications but can be more generally applied.
# =================================================================== # COMMON SPRING BOOT PROPERTIES # # This sample file is provided as a guideline. Do NOT copy it in its # entirety to your own application. ^^^ # =================================================================== # ---------------------------------------- # CORE PROPERTIES # ---------------------------------------- # BANNER banner.charset=UTF-8 # Banner file encoding. banner.location=classpath:banner.txt # Banner file location. banner.image.location=classpath:banner.gif # Banner image file location (jpg/png can also be used). banner.image.width= # Width of the banner image in chars (default 76) banner.image.height= # Height of the banner image in chars (default based on image height) banner.image.margin= # Left hand image margin in chars (default 2) banner.image.invert= # If images should be inverted for dark terminal themes (default false) # LOGGING logging.config= # Location of the logging configuration file. For instance `classpath:logback.xml` for Logback logging.exception-conversion-word=%wEx # Conversion word used when logging exceptions. logging.file= # Log file name. For instance `myapp.log` logging.level.*= # Log levels severity mapping. For instance `logging.level.org.springframework=DEBUG` logging.path= # Location of the log file. For instance `/var/log` logging.pattern.console= # Appender pattern for output to the console. Only supported with the default logback setup. logging.pattern.file= # Appender pattern for output to the file. Only supported with the default logback setup. logging.pattern.level= # Appender pattern for log level (default %5p). Only supported with the default logback setup. logging.register-shutdown-hook=false # Register a shutdown hook for the logging system when it is initialized. # AOP spring.aop.auto=true # Add @EnableAspectJAutoProxy. spring.aop.proxy-target-class=false # Whether subclass-based (CGLIB) proxies are to be created (true) as opposed to standard Java interface-based proxies (false). # IDENTITY (ContextIdApplicationContextInitializer) spring.application.index= # Application index. spring.application.name= # Application name. # ADMIN (SpringApplicationAdminJmxAutoConfiguration) spring.application.admin.enabled=false # Enable admin features for the application. spring.application.admin.jmx-name=org.springframework.boot:type=Admin,name=SpringApplication # JMX name of the application admin MBean. # AUTO-CONFIGURATION spring.autoconfigure.exclude= # Auto-configuration classes to exclude. # SPRING CORE spring.beaninfo.ignore=true # Skip search of BeanInfo classes. # SPRING CACHE (CacheProperties) spring.cache.cache-names= # Comma-separated list of cache names to create if supported by the underlying cache manager. spring.cache.caffeine.spec= # The spec to use to create caches. Check CaffeineSpec for more details on the spec format. spring.cache.couchbase.expiration=0 # Entry expiration in milliseconds. By default the entries never expire. spring.cache.ehcache.config= # The location of the configuration file to use to initialize EhCache. spring.cache.guava.spec= # The spec to use to create caches. Check CacheBuilderSpec for more details on the spec format. spring.cache.hazelcast.config= # The location of the configuration file to use to initialize Hazelcast. spring.cache.infinispan.config= # The location of the configuration file to use to initialize Infinispan. spring.cache.jcache.config= # The location of the configuration file to use to initialize the cache manager. spring.cache.jcache.provider= # Fully qualified name of the CachingProvider implementation to use to retrieve the JSR-107 compliant cache manager. Only needed if more than one JSR-107 implementation is available on the classpath. spring.cache.type= # Cache type, auto-detected according to the environment by default. # SPRING CONFIG - using environment property only (ConfigFileApplicationListener) spring.config.location= # Config file locations. spring.config.name=application # Config file name. # HAZELCAST (HazelcastProperties) spring.hazelcast.config= # The location of the configuration file to use to initialize Hazelcast. # PROJECT INFORMATION (ProjectInfoProperties) spring.info.build.location=classpath:META-INF/build-info.properties # Location of the generated build-info.properties file. spring.info.git.location=classpath:git.properties # Location of the generated git.properties file. # JMX spring.jmx.default-domain= # JMX domain name. spring.jmx.enabled=true # Expose management beans to the JMX domain. spring.jmx.server=mbeanServer # MBeanServer bean name. # Email (MailProperties) spring.mail.default-encoding=UTF-8 # Default MimeMessage encoding. spring.mail.host= # SMTP server host. For instance `smtp.example.com` spring.mail.jndi-name= # Session JNDI name. When set, takes precedence to others mail settings. spring.mail.password= # Login password of the SMTP server. spring.mail.port= # SMTP server port. spring.mail.properties.*= # Additional JavaMail session properties. spring.mail.protocol=smtp # Protocol used by the SMTP server. spring.mail.test-connection=false # Test that the mail server is available on startup. spring.mail.username= # Login user of the SMTP server. # APPLICATION SETTINGS (SpringApplication) spring.main.banner-mode=console # Mode used to display the banner when the application runs. spring.main.sources= # Sources (class name, package name or XML resource location) to include in the ApplicationContext. spring.main.web-environment= # Run the application in a web environment (auto-detected by default). # FILE ENCODING (FileEncodingApplicationListener) spring.mandatory-file-encoding= # Expected character encoding the application must use. # INTERNATIONALIZATION (MessageSourceAutoConfiguration) spring.messages.always-use-message-format=false # Set whether to always apply the MessageFormat rules, parsing even messages without arguments. spring.messages.basename=messages # Comma-separated list of basenames, each following the ResourceBundle convention. spring.messages.cache-seconds=-1 # Loaded resource bundle files cache expiration, in seconds. When set to -1, bundles are cached forever. spring.messages.encoding=UTF-8 # Message bundles encoding. spring.messages.fallback-to-system-locale=true # Set whether to fall back to the system Locale if no files for a specific Locale have been found. # OUTPUT spring.output.ansi.enabled=detect # Configure the ANSI output (can be "detect", "always", "never"). # PID FILE (ApplicationPidFileWriter) spring.pid.fail-on-write-error= # Fail if ApplicationPidFileWriter is used but it cannot write the PID file. spring.pid.file= # Location of the PID file to write (if ApplicationPidFileWriter is used). # PROFILES spring.profiles.active= # Comma-separated list of active profiles. spring.profiles.include= # Unconditionally activate the specified comma separated profiles. # SENDGRID (SendGridAutoConfiguration) spring.sendgrid.api-key= # SendGrid api key (alternative to username/password) spring.sendgrid.username= # SendGrid account username spring.sendgrid.password= # SendGrid account password spring.sendgrid.proxy.host= # SendGrid proxy host spring.sendgrid.proxy.port= # SendGrid proxy port # ---------------------------------------- # WEB PROPERTIES # ---------------------------------------- # EMBEDDED SERVER CONFIGURATION (ServerProperties) server.address= # Network address to which the server should bind to. server.compression.enabled=false # If response compression is enabled. server.compression.excluded-user-agents= # List of user-agents to exclude from compression. server.compression.mime-types= # Comma-separated list of MIME types that should be compressed. For instance `text/html,text/css,application/json` server.compression.min-response-size= # Minimum response size that is required for compression to be performed. For instance 2048 server.connection-timeout= # Time in milliseconds that connectors will wait for another HTTP request before closing the connection. When not set, the connector's container-specific default will be used. Use a value of -1 to indicate no (i.e. infinite) timeout. server.context-parameters.*= # Servlet context init parameters. For instance `server.context-parameters.a=alpha` server.context-path= # Context path of the application. server.display-name=application # Display name of the application. server.max-http-header-size=0 # Maximum size in bytes of the HTTP message header. server.max-http-post-size=0 # Maximum size in bytes of the HTTP post content. server.error.include-stacktrace=never # When to include a "stacktrace" attribute. server.error.path=/error # Path of the error controller. server.error.whitelabel.enabled=true # Enable the default error page displayed in browsers in case of a server error. server.jetty.acceptors= # Number of acceptor threads to use. server.jetty.selectors= # Number of selector threads to use. server.jsp-servlet.class-name=org.apache.jasper.servlet.JspServlet # The class name of the JSP servlet. server.jsp-servlet.init-parameters.*= # Init parameters used to configure the JSP servlet server.jsp-servlet.registered=true # Whether or not the JSP servlet is registered server.port=8080 # Server HTTP port. server.server-header= # Value to use for the Server response header (no header is sent if empty) server.servlet-path=/ # Path of the main dispatcher servlet. server.use-forward-headers= # If X-Forwarded-* headers should be applied to the HttpRequest. server.session.cookie.comment= # Comment for the session cookie. server.session.cookie.domain= # Domain for the session cookie. server.session.cookie.http-only= # "HttpOnly" flag for the session cookie. server.session.cookie.max-age= # Maximum age of the session cookie in seconds. server.session.cookie.name= # Session cookie name. server.session.cookie.path= # Path of the session cookie. server.session.cookie.secure= # "Secure" flag for the session cookie. server.session.persistent=false # Persist session data between restarts. server.session.store-dir= # Directory used to store session data. server.session.timeout= # Session timeout in seconds. server.session.tracking-modes= # Session tracking modes (one or more of the following: "cookie", "url", "ssl"). server.ssl.ciphers= # Supported SSL ciphers. server.ssl.client-auth= # Whether client authentication is wanted ("want") or needed ("need"). Requires a trust store. server.ssl.enabled= # Enable SSL support. server.ssl.enabled-protocols= # Enabled SSL protocols. server.ssl.key-alias= # Alias that identifies the key in the key store. server.ssl.key-password= # Password used to access the key in the key store. server.ssl.key-store= # Path to the key store that holds the SSL certificate (typically a jks file). server.ssl.key-store-password= # Password used to access the key store. server.ssl.key-store-provider= # Provider for the key store. server.ssl.key-store-type= # Type of the key store. server.ssl.protocol=TLS # SSL protocol to use. server.ssl.trust-store= # Trust store that holds SSL certificates. server.ssl.trust-store-password= # Password used to access the trust store. server.ssl.trust-store-provider= # Provider for the trust store. server.ssl.trust-store-type= # Type of the trust store. server.tomcat.accesslog.directory=logs # Directory in which log files are created. Can be relative to the tomcat base dir or absolute. server.tomcat.accesslog.enabled=false # Enable access log. server.tomcat.accesslog.pattern=common # Format pattern for access logs. server.tomcat.accesslog.prefix=access_log # Log file name prefix. server.tomcat.accesslog.rename-on-rotate=false # Defer inclusion of the date stamp in the file name until rotate time. server.tomcat.accesslog.suffix=.log # Log file name suffix. server.tomcat.background-processor-delay=30 # Delay in seconds between the invocation of backgroundProcess methods. server.tomcat.basedir= # Tomcat base directory. If not specified a temporary directory will be used. server.tomcat.internal-proxies=10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|\\ 192\\.168\\.\\d{1,3}\\.\\d{1,3}|\\ 169\\.254\\.\\d{1,3}\\.\\d{1,3}|\\ 127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|\\ 172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|\\ 172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|\\ 172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3} # regular expression matching trusted IP addresses. server.tomcat.max-threads=0 # Maximum amount of worker threads. server.tomcat.min-spare-threads=0 # Minimum amount of worker threads. server.tomcat.port-header=X-Forwarded-Port # Name of the HTTP header used to override the original port value. server.tomcat.protocol-header= # Header that holds the incoming protocol, usually named "X-Forwarded-Proto". server.tomcat.protocol-header-https-value=https # Value of the protocol header that indicates that the incoming request uses SSL. server.tomcat.redirect-context-root= # Whether requests to the context root should be redirected by appending a / to the path. server.tomcat.remote-ip-header= # Name of the http header from which the remote ip is extracted. For instance `X-FORWARDED-FOR` server.tomcat.uri-encoding=UTF-8 # Character encoding to use to decode the URI. server.undertow.accesslog.dir= # Undertow access log directory. server.undertow.accesslog.enabled=false # Enable access log. server.undertow.accesslog.pattern=common # Format pattern for access logs. server.undertow.buffer-size= # Size of each buffer in bytes. server.undertow.buffers-per-region= # Number of buffer per region. server.undertow.direct-buffers= # Allocate buffers outside the Java heap. server.undertow.io-threads= # Number of I/O threads to create for the worker. server.undertow.worker-threads= # Number of worker threads. # FREEMARKER (FreeMarkerAutoConfiguration) spring.freemarker.allow-request-override=false # Set whether HttpServletRequest attributes are allowed to override (hide) controller generated model attributes of the same name. spring.freemarker.allow-session-override=false # Set whether HttpSession attributes are allowed to override (hide) controller generated model attributes of the same name. spring.freemarker.cache=false # Enable template caching. spring.freemarker.charset=UTF-8 # Template encoding. spring.freemarker.check-template-location=true # Check that the templates location exists. spring.freemarker.content-type=text/html # Content-Type value. spring.freemarker.enabled=true # Enable MVC view resolution for this technology. spring.freemarker.expose-request-attributes=false # Set whether all request attributes should be added to the model prior to merging with the template. spring.freemarker.expose-session-attributes=false # Set whether all HttpSession attributes should be added to the model prior to merging with the template. spring.freemarker.expose-spring-macro-helpers=true # Set whether to expose a RequestContext for use by Spring's macro library, under the name "springMacroRequestContext". spring.freemarker.prefer-file-system-access=true # Prefer file system access for template loading. File system access enables hot detection of template changes. spring.freemarker.prefix= # Prefix that gets prepended to view names when building a URL. spring.freemarker.request-context-attribute= # Name of the RequestContext attribute for all views. spring.freemarker.settings.*= # Well-known FreeMarker keys which will be passed to FreeMarker's Configuration. spring.freemarker.suffix= # Suffix that gets appended to view names when building a URL. spring.freemarker.template-loader-path=classpath:/templates/ # Comma-separated list of template paths. spring.freemarker.view-names= # White list of view names that can be resolved. # GROOVY TEMPLATES (GroovyTemplateAutoConfiguration) spring.groovy.template.allow-request-override=false # Set whether HttpServletRequest attributes are allowed to override (hide) controller generated model attributes of the same name. spring.groovy.template.allow-session-override=false # Set whether HttpSession attributes are allowed to override (hide) controller generated model attributes of the same name. spring.groovy.template.cache= # Enable template caching. spring.groovy.template.charset=UTF-8 # Template encoding. spring.groovy.template.check-template-location=true # Check that the templates location exists. spring.groovy.template.configuration.*= # See GroovyMarkupConfigurer spring.groovy.template.content-type=test/html # Content-Type value. spring.groovy.template.enabled=true # Enable MVC view resolution for this technology. spring.groovy.template.expose-request-attributes=false # Set whether all request attributes should be added to the model prior to merging with the template. spring.groovy.template.expose-session-attributes=false # Set whether all HttpSession attributes should be added to the model prior to merging with the template. spring.groovy.template.expose-spring-macro-helpers=true # Set whether to expose a RequestContext for use by Spring's macro library, under the name "springMacroRequestContext". spring.groovy.template.prefix= # Prefix that gets prepended to view names when building a URL. spring.groovy.template.request-context-attribute= # Name of the RequestContext attribute for all views. spring.groovy.template.resource-loader-path=classpath:/templates/ # Template path. spring.groovy.template.suffix=.tpl # Suffix that gets appended to view names when building a URL. spring.groovy.template.view-names= # White list of view names that can be resolved. # SPRING HATEOAS (HateoasProperties) spring.hateoas.use-hal-as-default-json-media-type=true # Specify if application/hal+json responses should be sent to requests that accept application/json. # HTTP message conversion spring.http.converters.preferred-json-mapper=jackson # Preferred JSON mapper to use for HTTP message conversion. Set to "gson" to force the use of Gson when both it and Jackson are on the classpath. # HTTP encoding (HttpEncodingProperties) spring.http.encoding.charset=UTF-8 # Charset of HTTP requests and responses. Added to the "Content-Type" header if not set explicitly. spring.http.encoding.enabled=true # Enable http encoding support. spring.http.encoding.force= # Force the encoding to the configured charset on HTTP requests and responses. spring.http.encoding.force-request= # Force the encoding to the configured charset on HTTP requests. Defaults to true when "force" has not been specified. spring.http.encoding.force-response= # Force the encoding to the configured charset on HTTP responses. # MULTIPART (MultipartProperties) spring.http.multipart.enabled=true # Enable support of multi-part uploads. spring.http.multipart.file-size-threshold=0 # Threshold after which files will be written to disk. Values can use the suffixed "MB" or "KB" to indicate a Megabyte or Kilobyte size. spring.http.multipart.location= # Intermediate location of uploaded files. spring.http.multipart.max-file-size=1Mb # Max file size. Values can use the suffixed "MB" or "KB" to indicate a Megabyte or Kilobyte size. spring.http.multipart.max-request-size=10Mb # Max request size. Values can use the suffixed "MB" or "KB" to indicate a Megabyte or Kilobyte size. # JACKSON (JacksonProperties) spring.jackson.date-format= # Date format string or a fully-qualified date format class name. For instance `yyyy-MM-dd HH:mm:ss`. spring.jackson.default-property-inclusion= # Controls the inclusion of properties during serialization. spring.jackson.deserialization.*= # Jackson on/off features that affect the way Java objects are deserialized. spring.jackson.generator.*= # Jackson on/off features for generators. spring.jackson.joda-date-time-format= # Joda date time format string. If not configured, "date-format" will be used as a fallback if it is configured with a format string. spring.jackson.locale= # Locale used for formatting. spring.jackson.mapper.*= # Jackson general purpose on/off features. spring.jackson.parser.*= # Jackson on/off features for parsers. spring.jackson.property-naming-strategy= # One of the constants on Jackson's PropertyNamingStrategy. Can also be a fully-qualified class name of a PropertyNamingStrategy subclass. spring.jackson.serialization.*= # Jackson on/off features that affect the way Java objects are serialized. spring.jackson.serialization-inclusion= # Controls the inclusion of properties during serialization. Configured with one of the values in Jackson's JsonInclude.Include enumeration. spring.jackson.time-zone= # Time zone used when formatting dates. For instance `America/Los_Angeles` # JERSEY (JerseyProperties) spring.jersey.application-path= # Path that serves as the base URI for the application. Overrides the value of "@ApplicationPath" if specified. spring.jersey.filter.order=0 # Jersey filter chain order. spring.jersey.init.*= # Init parameters to pass to Jersey via the servlet or filter. spring.jersey.servlet.load-on-startup=-1 # Load on startup priority of the Jersey servlet. spring.jersey.type=servlet # Jersey integration type. Can be either "servlet" or "filter". # SPRING MOBILE DEVICE VIEWS (DeviceDelegatingViewResolverAutoConfiguration) spring.mobile.devicedelegatingviewresolver.enable-fallback=false # Enable support for fallback resolution. spring.mobile.devicedelegatingviewresolver.enabled=false # Enable device view resolver. spring.mobile.devicedelegatingviewresolver.mobile-prefix=mobile/ # Prefix that gets prepended to view names for mobile devices. spring.mobile.devicedelegatingviewresolver.mobile-suffix= # Suffix that gets appended to view names for mobile devices. spring.mobile.devicedelegatingviewresolver.normal-prefix= # Prefix that gets prepended to view names for normal devices. spring.mobile.devicedelegatingviewresolver.normal-suffix= # Suffix that gets appended to view names for normal devices. spring.mobile.devicedelegatingviewresolver.tablet-prefix=tablet/ # Prefix that gets prepended to view names for tablet devices. spring.mobile.devicedelegatingviewresolver.tablet-suffix= # Suffix that gets appended to view names for tablet devices. # SPRING MOBILE SITE PREFERENCE (SitePreferenceAutoConfiguration) spring.mobile.sitepreference.enabled=true # Enable SitePreferenceHandler. # MUSTACHE TEMPLATES (MustacheAutoConfiguration) spring.mustache.allow-request-override= # Set whether HttpServletRequest attributes are allowed to override (hide) controller generated model attributes of the same name. spring.mustache.allow-session-override= # Set whether HttpSession attributes are allowed to override (hide) controller generated model attributes of the same name. spring.mustache.cache= # Enable template caching. spring.mustache.charset= # Template encoding. spring.mustache.check-template-location= # Check that the templates location exists. spring.mustache.content-type= # Content-Type value. spring.mustache.enabled= # Enable MVC view resolution for this technology. spring.mustache.expose-request-attributes= # Set whether all request attributes should be added to the model prior to merging with the template. spring.mustache.expose-session-attributes= # Set whether all HttpSession attributes should be added to the model prior to merging with the template. spring.mustache.expose-spring-macro-helpers= # Set whether to expose a RequestContext for use by Spring's macro library, under the name "springMacroRequestContext". spring.mustache.prefix=classpath:/templates/ # Prefix to apply to template names. spring.mustache.request-context-attribute= # Name of the RequestContext attribute for all views. spring.mustache.suffix=.html # Suffix to apply to template names. spring.mustache.view-names= # White list of view names that can be resolved. # SPRING MVC (WebMvcProperties) spring.mvc.async.request-timeout= # Amount of time (in milliseconds) before asynchronous request handling times out. spring.mvc.date-format= # Date format to use. For instance `dd/MM/yyyy`. spring.mvc.dispatch-trace-request=false # Dispatch TRACE requests to the FrameworkServlet doService method. spring.mvc.dispatch-options-request=true # Dispatch OPTIONS requests to the FrameworkServlet doService method. spring.mvc.favicon.enabled=true # Enable resolution of favicon.ico. spring.mvc.ignore-default-model-on-redirect=true # If the content of the "default" model should be ignored during redirect scenarios. spring.mvc.locale= # Locale to use. By default, this locale is overridden by the "Accept-Language" header. spring.mvc.locale-resolver=accept-header # Define how the locale should be resolved. spring.mvc.log-resolved-exception=false # Enable warn logging of exceptions resolved by a "HandlerExceptionResolver". spring.mvc.media-types.*= # Maps file extensions to media types for content negotiation. spring.mvc.message-codes-resolver-format= # Formatting strategy for message codes. For instance `PREFIX_ERROR_CODE`. spring.mvc.servlet.load-on-startup=-1 # Load on startup priority of the Spring Web Services servlet. spring.mvc.static-path-pattern=/** # Path pattern used for static resources. spring.mvc.throw-exception-if-no-handler-found=false # If a "NoHandlerFoundException" should be thrown if no Handler was found to process a request. spring.mvc.view.prefix= # Spring MVC view prefix. spring.mvc.view.suffix= # Spring MVC view suffix. # SPRING RESOURCES HANDLING (ResourceProperties) spring.resources.add-mappings=true # Enable default resource handling. spring.resources.cache-period= # Cache period for the resources served by the resource handler, in seconds. spring.resources.chain.cache=true # Enable caching in the Resource chain. spring.resources.chain.enabled= # Enable the Spring Resource Handling chain. Disabled by default unless at least one strategy has been enabled. spring.resources.chain.gzipped=false # Enable resolution of already gzipped resources. spring.resources.chain.html-application-cache=false # Enable HTML5 application cache manifest rewriting. spring.resources.chain.strategy.content.enabled=false # Enable the content Version Strategy. spring.resources.chain.strategy.content.paths=/** # Comma-separated list of patterns to apply to the Version Strategy. spring.resources.chain.strategy.fixed.enabled=false # Enable the fixed Version Strategy. spring.resources.chain.strategy.fixed.paths=/** # Comma-separated list of patterns to apply to the Version Strategy. spring.resources.chain.strategy.fixed.version= # Version string to use for the Version Strategy. spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/ # Locations of static resources. # SPRING SESSION (SessionProperties) spring.session.hazelcast.map-name=spring:session:sessions # Name of the map used to store sessions. spring.session.jdbc.initializer.enabled=true # Create the required session tables on startup if necessary. spring.session.jdbc.schema=classpath:org/springframework/session/jdbc/schema-@@platform@@.sql # Path to the SQL file to use to initialize the database schema. spring.session.jdbc.table-name=SPRING_SESSION # Name of database table used to store sessions. spring.session.mongo.collection-name=sessions # Collection name used to store sessions. spring.session.redis.flush-mode= # Flush mode for the Redis sessions. spring.session.redis.namespace= # Namespace for keys used to store sessions. spring.session.store-type= # Session store type. # SPRING SOCIAL (SocialWebAutoConfiguration) spring.social.auto-connection-views=false # Enable the connection status view for supported providers. # SPRING SOCIAL FACEBOOK (FacebookAutoConfiguration) spring.social.facebook.app-id= # your application's Facebook App ID spring.social.facebook.app-secret= # your application's Facebook App Secret # SPRING SOCIAL LINKEDIN (LinkedInAutoConfiguration) spring.social.linkedin.app-id= # your application's LinkedIn App ID spring.social.linkedin.app-secret= # your application's LinkedIn App Secret # SPRING SOCIAL TWITTER (TwitterAutoConfiguration) spring.social.twitter.app-id= # your application's Twitter App ID spring.social.twitter.app-secret= # your application's Twitter App Secret # THYMELEAF (ThymeleafAutoConfiguration) spring.thymeleaf.cache=true # Enable template caching. spring.thymeleaf.check-template-location=true # Check that the templates location exists. spring.thymeleaf.content-type=text/html # Content-Type value. spring.thymeleaf.enabled=true # Enable MVC Thymeleaf view resolution. spring.thymeleaf.encoding=UTF-8 # Template encoding. spring.thymeleaf.excluded-view-names= # Comma-separated list of view names that should be excluded from resolution. spring.thymeleaf.mode=HTML5 # Template mode to be applied to templates. See also StandardTemplateModeHandlers. spring.thymeleaf.prefix=classpath:/templates/ # Prefix that gets prepended to view names when building a URL. spring.thymeleaf.suffix=.html # Suffix that gets appended to view names when building a URL. spring.thymeleaf.template-resolver-order= # Order of the template resolver in the chain. spring.thymeleaf.view-names= # Comma-separated list of view names that can be resolved. # VELOCITY TEMPLATES (VelocityAutoConfiguration) spring.velocity.allow-request-override=false # Set whether HttpServletRequest attributes are allowed to override (hide) controller generated model attributes of the same name. spring.velocity.allow-session-override=false # Set whether HttpSession attributes are allowed to override (hide) controller generated model attributes of the same name. spring.velocity.cache= # Enable template caching. spring.velocity.charset=UTF-8 # Template encoding. spring.velocity.check-template-location=true # Check that the templates location exists. spring.velocity.content-type=text/html # Content-Type value. spring.velocity.date-tool-attribute= # Name of the DateTool helper object to expose in the Velocity context of the view. spring.velocity.enabled=true # Enable MVC view resolution for this technology. spring.velocity.expose-request-attributes=false # Set whether all request attributes should be added to the model prior to merging with the template. spring.velocity.expose-session-attributes=false # Set whether all HttpSession attributes should be added to the model prior to merging with the template. spring.velocity.expose-spring-macro-helpers=true # Set whether to expose a RequestContext for use by Spring's macro library, under the name "springMacroRequestContext". spring.velocity.number-tool-attribute= # Name of the NumberTool helper object to expose in the Velocity context of the view. spring.velocity.prefer-file-system-access=true # Prefer file system access for template loading. File system access enables hot detection of template changes. spring.velocity.prefix= # Prefix that gets prepended to view names when building a URL. spring.velocity.properties.*= # Additional velocity properties. spring.velocity.request-context-attribute= # Name of the RequestContext attribute for all views. spring.velocity.resource-loader-path=classpath:/templates/ # Template path. spring.velocity.suffix=.vm # Suffix that gets appended to view names when building a URL. spring.velocity.toolbox-config-location= # Velocity Toolbox config location. For instance `/WEB-INF/toolbox.xml` spring.velocity.view-names= # White list of view names that can be resolved. # SPRING WEB SERVICES (WebServicesProperties) spring.webservices.path=/services # Path that serves as the base URI for the services. spring.webservices.servlet.init= # Servlet init parameters to pass to Spring Web Services. spring.webservices.servlet.load-on-startup=-1 # Load on startup priority of the Spring Web Services servlet. # ---------------------------------------- # SECURITY PROPERTIES # ---------------------------------------- # SECURITY (SecurityProperties) security.basic.authorize-mode=role # Security authorize mode to apply. security.basic.enabled=true # Enable basic authentication. security.basic.path=/** # Comma-separated list of paths to secure. security.basic.realm=Spring # HTTP basic realm name. security.enable-csrf=false # Enable Cross Site Request Forgery support. security.filter-order=0 # Security filter chain order. security.filter-dispatcher-types=ASYNC, FORWARD, INCLUDE, REQUEST # Security filter chain dispatcher types. security.headers.cache=true # Enable cache control HTTP headers. security.headers.content-type=true # Enable "X-Content-Type-Options" header. security.headers.frame=true # Enable "X-Frame-Options" header. security.headers.hsts= # HTTP Strict Transport Security (HSTS) mode (none, domain, all). security.headers.xss=true # Enable cross site scripting (XSS) protection. security.ignored= # Comma-separated list of paths to exclude from the default secured paths. security.require-ssl=false # Enable secure channel for all requests. security.sessions=stateless # Session creation policy (always, never, if_required, stateless). security.user.name=user # Default user name. security.user.password= # Password for the default user name. A random password is logged on startup by default. security.user.role=USER # Granted roles for the default user name. # SECURITY OAUTH2 CLIENT (OAuth2ClientProperties security.oauth2.client.client-id= # OAuth2 client id. security.oauth2.client.client-secret= # OAuth2 client secret. A random secret is generated by default # SECURITY OAUTH2 RESOURCES (ResourceServerProperties security.oauth2.resource.id= # Identifier of the resource. security.oauth2.resource.jwt.key-uri= # The URI of the JWT token. Can be set if the value is not available and the key is public. security.oauth2.resource.jwt.key-value= # The verification key of the JWT token. Can either be a symmetric secret or PEM-encoded RSA public key. security.oauth2.resource.prefer-token-info=true # Use the token info, can be set to false to use the user info. security.oauth2.resource.service-id=resource # security.oauth2.resource.token-info-uri= # URI of the token decoding endpoint. security.oauth2.resource.token-type= # The token type to send when using the userInfoUri. security.oauth2.resource.user-info-uri= # URI of the user endpoint. # SECURITY OAUTH2 SSO (OAuth2SsoProperties security.oauth2.sso.filter-order= # Filter order to apply if not providing an explicit WebSecurityConfigurerAdapter security.oauth2.sso.login-path=/login # Path to the login page, i.e. the one that triggers the redirect to the OAuth2 Authorization Server # ---------------------------------------- # DATA PROPERTIES # ---------------------------------------- # FLYWAY (FlywayProperties) flyway.baseline-description= # flyway.baseline-version=1 # version to start migration flyway.baseline-on-migrate= # flyway.check-location=false # Check that migration scripts location exists. flyway.clean-on-validation-error= # flyway.enabled=true # Enable flyway. flyway.encoding= # flyway.ignore-failed-future-migration= # flyway.init-sqls= # SQL statements to execute to initialize a connection immediately after obtaining it. flyway.locations=classpath:db/migration # locations of migrations scripts flyway.out-of-order= # flyway.password= # JDBC password if you want Flyway to create its own DataSource flyway.placeholder-prefix= # flyway.placeholder-replacement= # flyway.placeholder-suffix= # flyway.placeholders.*= # flyway.schemas= # schemas to update flyway.sql-migration-prefix=V # flyway.sql-migration-separator= # flyway.sql-migration-suffix=.sql # flyway.table= # flyway.url= # JDBC url of the database to migrate. If not set, the primary configured data source is used. flyway.user= # Login user of the database to migrate. flyway.validate-on-migrate= # # LIQUIBASE (LiquibaseProperties) liquibase.change-log=classpath:/db/changelog/db.changelog-master.yaml # Change log configuration path. liquibase.check-change-log-location=true # Check the change log location exists. liquibase.contexts= # Comma-separated list of runtime contexts to use. liquibase.default-schema= # Default database schema. liquibase.drop-first=false # Drop the database schema first. liquibase.enabled=true # Enable liquibase support. liquibase.labels= # Comma-separated list of runtime labels to use. liquibase.parameters.*= # Change log parameters. liquibase.password= # Login password of the database to migrate. liquibase.rollback-file= # File to which rollback SQL will be written when an update is performed. liquibase.url= # JDBC url of the database to migrate. If not set, the primary configured data source is used. liquibase.user= # Login user of the database to migrate. # COUCHBASE (CouchbaseProperties) spring.couchbase.bootstrap-hosts= # Couchbase nodes (host or IP address) to bootstrap from. spring.couchbase.bucket.name=default # Name of the bucket to connect to. spring.couchbase.bucket.password= # Password of the bucket. spring.couchbase.env.endpoints.key-value=1 # Number of sockets per node against the Key/value service. spring.couchbase.env.endpoints.query=1 # Number of sockets per node against the Query (N1QL) service. spring.couchbase.env.endpoints.view=1 # Number of sockets per node against the view service. spring.couchbase.env.ssl.enabled= # Enable SSL support. Enabled automatically if a "keyStore" is provided unless specified otherwise. spring.couchbase.env.ssl.key-store= # Path to the JVM key store that holds the certificates. spring.couchbase.env.ssl.key-store-password= # Password used to access the key store. spring.couchbase.env.timeouts.connect=5000 # Bucket connections timeout in milliseconds. spring.couchbase.env.timeouts.key-value=2500 # Blocking operations performed on a specific key timeout in milliseconds. spring.couchbase.env.timeouts.query=7500 # N1QL query operations timeout in milliseconds. spring.couchbase.env.timeouts.socket-connect=1000 # Socket connect connections timeout in milliseconds. spring.couchbase.env.timeouts.view=7500 # Regular and geospatial view operations timeout in milliseconds. # DAO (PersistenceExceptionTranslationAutoConfiguration) spring.dao.exceptiontranslation.enabled=true # Enable the PersistenceExceptionTranslationPostProcessor. # CASSANDRA (CassandraProperties) spring.data.cassandra.cluster-name= # Name of the Cassandra cluster. spring.data.cassandra.compression= # Compression supported by the Cassandra binary protocol. spring.data.cassandra.connect-timeout-millis= # Socket option: connection time out. spring.data.cassandra.consistency-level= # Queries consistency level. spring.data.cassandra.contact-points=localhost # Comma-separated list of cluster node addresses. spring.data.cassandra.fetch-size= # Queries default fetch size. spring.data.cassandra.keyspace-name= # Keyspace name to use. spring.data.cassandra.load-balancing-policy= # Class name of the load balancing policy. spring.data.cassandra.port= # Port of the Cassandra server. spring.data.cassandra.password= # Login password of the server. spring.data.cassandra.read-timeout-millis= # Socket option: read time out. spring.data.cassandra.reconnection-policy= # Reconnection policy class. spring.data.cassandra.retry-policy= # Class name of the retry policy. spring.data.cassandra.serial-consistency-level= # Queries serial consistency level. spring.data.cassandra.schema-action=none # Schema action to take at startup. spring.data.cassandra.ssl=false # Enable SSL support. spring.data.cassandra.username= # Login user of the server. # DATA COUCHBASE (CouchbaseDataProperties) spring.data.couchbase.auto-index=false # Automatically create views and indexes. spring.data.couchbase.consistency=read-your-own-writes # Consistency to apply by default on generated queries. spring.data.couchbase.repositories.enabled=true # Enable Couchbase repositories. # ELASTICSEARCH (ElasticsearchProperties) spring.data.elasticsearch.cluster-name=elasticsearch # Elasticsearch cluster name. spring.data.elasticsearch.cluster-nodes= # Comma-separated list of cluster node addresses. If not specified, starts a client node. spring.data.elasticsearch.properties.*= # Additional properties used to configure the client. spring.data.elasticsearch.repositories.enabled=true # Enable Elasticsearch repositories. # MONGODB (MongoProperties) spring.data.mongodb.authentication-database= # Authentication database name. spring.data.mongodb.database=test # Database name. spring.data.mongodb.field-naming-strategy= # Fully qualified name of the FieldNamingStrategy to use. spring.data.mongodb.grid-fs-database= # GridFS database name. spring.data.mongodb.host=localhost # Mongo server host. spring.data.mongodb.password= # Login password of the mongo server. spring.data.mongodb.port=27017 # Mongo server port. spring.data.mongodb.repositories.enabled=true # Enable Mongo repositories. spring.data.mongodb.uri=mongodb://localhost/test # Mongo database URI. When set, host and port are ignored. spring.data.mongodb.username= # Login user of the mongo server. # DATA REDIS spring.data.redis.repositories.enabled=true # Enable Redis repositories. # NEO4J (Neo4jProperties) spring.data.neo4j.compiler= # Compiler to use. spring.data.neo4j.embedded.enabled=true # Enable embedded mode if the embedded driver is available. spring.data.neo4j.password= # Login password of the server. spring.data.neo4j.repositories.enabled=true # Enable Neo4j repositories. spring.data.neo4j.session.scope=singleton # Scope (lifetime) of the session. spring.data.neo4j.uri= # URI used by the driver. Auto-detected by default. spring.data.neo4j.username= # Login user of the server. # DATA REST (RepositoryRestProperties) spring.data.rest.base-path= # Base path to be used by Spring Data REST to expose repository resources. spring.data.rest.default-page-size= # Default size of pages. spring.data.rest.enable-enum-translation= # Enable enum value translation via the Spring Data REST default resource bundle. spring.data.rest.limit-param-name= # Name of the URL query string parameter that indicates how many results to return at once. spring.data.rest.max-page-size= # Maximum size of pages. spring.data.rest.page-param-name= # Name of the URL query string parameter that indicates what page to return. spring.data.rest.return-body-on-create= # Return a response body after creating an entity. spring.data.rest.return-body-on-update= # Return a response body after updating an entity. spring.data.rest.sort-param-name= # Name of the URL query string parameter that indicates what direction to sort results. # SOLR (SolrProperties) spring.data.solr.host=http://127.0.0.1:8983/solr # Solr host. Ignored if "zk-host" is set. spring.data.solr.repositories.enabled=true # Enable Solr repositories. spring.data.solr.zk-host= # ZooKeeper host address in the form HOST:PORT. # DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties) spring.datasource.continue-on-error=false # Do not stop if an error occurs while initializing the database. spring.datasource.data= # Data (DML) script resource reference. spring.datasource.data-username= # User of the database to execute DML scripts (if different). spring.datasource.data-password= # Password of the database to execute DML scripts (if different). spring.datasource.dbcp.*= # Commons DBCP specific settings spring.datasource.dbcp2.*= # Commons DBCP2 specific settings spring.datasource.driver-class-name= # Fully qualified name of the JDBC driver. Auto-detected based on the URL by default. spring.datasource.hikari.*= # Hikari specific settings spring.datasource.initialize=true # Populate the database using 'data.sql'. spring.datasource.jmx-enabled=false # Enable JMX support (if provided by the underlying pool). spring.datasource.jndi-name= # JNDI location of the datasource. Class, url, username & password are ignored when set. spring.datasource.name=testdb # Name of the datasource. spring.datasource.password= # Login password of the database. spring.datasource.platform=all # Platform to use in the schema resource (schema-${platform}.sql). spring.datasource.schema= # Schema (DDL) script resource reference. spring.datasource.schema-username= # User of the database to execute DDL scripts (if different). spring.datasource.schema-password= # Password of the database to execute DDL scripts (if different). spring.datasource.separator=; # Statement separator in SQL initialization scripts. spring.datasource.sql-script-encoding= # SQL scripts encoding. spring.datasource.tomcat.*= # Tomcat datasource specific settings spring.datasource.type= # Fully qualified name of the connection pool implementation to use. By default, it is auto-detected from the classpath. spring.datasource.url= # JDBC url of the database. spring.datasource.username= # JEST (Elasticsearch HTTP client) (JestProperties) spring.elasticsearch.jest.connection-timeout=3000 # Connection timeout in milliseconds. spring.elasticsearch.jest.password= # Login password. spring.elasticsearch.jest.proxy.host= # Proxy host the HTTP client should use. spring.elasticsearch.jest.proxy.port= # Proxy port the HTTP client should use. spring.elasticsearch.jest.read-timeout=3000 # Read timeout in milliseconds. spring.elasticsearch.jest.uris=http://localhost:9200 # Comma-separated list of the Elasticsearch instances to use. spring.elasticsearch.jest.username= # Login user. # H2 Web Console (H2ConsoleProperties) spring.h2.console.enabled=false # Enable the console. spring.h2.console.path=/h2-console # Path at which the console will be available. spring.h2.console.settings.trace=false # Enable trace output. spring.h2.console.settings.web-allow-others=false # Enable remote access. # JOOQ (JooqAutoConfiguration) spring.jooq.sql-dialect= # SQLDialect JOOQ used when communicating with the configured datasource. For instance `POSTGRES` # JPA (JpaBaseConfiguration, HibernateJpaAutoConfiguration) spring.data.jpa.repositories.enabled=true # Enable JPA repositories. spring.jpa.database= # Target database to operate on, auto-detected by default. Can be alternatively set using the "databasePlatform" property. spring.jpa.database-platform= # Name of the target database to operate on, auto-detected by default. Can be alternatively set using the "Database" enum. spring.jpa.generate-ddl=false # Initialize the schema on startup. spring.jpa.hibernate.ddl-auto= # DDL mode. This is actually a shortcut for the "hibernate.hbm2ddl.auto" property. Default to "create-drop" when using an embedded database, "none" otherwise. spring.jpa.hibernate.naming.implicit-strategy= # Hibernate 5 implicit naming strategy fully qualified name. spring.jpa.hibernate.naming.physical-strategy= # Hibernate 5 physical naming strategy fully qualified name. spring.jpa.hibernate.naming.strategy= # Hibernate 4 naming strategy fully qualified name. Not supported with Hibernate 5. spring.jpa.hibernate.use-new-id-generator-mappings= # Use Hibernate's newer IdentifierGenerator for AUTO, TABLE and SEQUENCE. spring.jpa.open-in-view=true # Register OpenEntityManagerInViewInterceptor. Binds a JPA EntityManager to the thread for the entire processing of the request. spring.jpa.properties.*= # Additional native properties to set on the JPA provider. spring.jpa.show-sql=false # Enable logging of SQL statements. # JTA (JtaAutoConfiguration) spring.jta.enabled=true # Enable JTA support. spring.jta.log-dir= # Transaction logs directory. spring.jta.transaction-manager-id= # Transaction manager unique identifier. # ATOMIKOS (AtomikosProperties) spring.jta.atomikos.connectionfactory.borrow-connection-timeout=30 # Timeout, in seconds, for borrowing connections from the pool. spring.jta.atomikos.connectionfactory.ignore-session-transacted-flag=true # Whether or not to ignore the transacted flag when creating session. spring.jta.atomikos.connectionfactory.local-transaction-mode=false # Whether or not local transactions are desired. spring.jta.atomikos.connectionfactory.maintenance-interval=60 # The time, in seconds, between runs of the pool's maintenance thread. spring.jta.atomikos.connectionfactory.max-idle-time=60 # The time, in seconds, after which connections are cleaned up from the pool. spring.jta.atomikos.connectionfactory.max-lifetime=0 # The time, in seconds, that a connection can be pooled for before being destroyed. 0 denotes no limit. spring.jta.atomikos.connectionfactory.max-pool-size=1 # The maximum size of the pool. spring.jta.atomikos.connectionfactory.min-pool-size=1 # The minimum size of the pool. spring.jta.atomikos.connectionfactory.reap-timeout=0 # The reap timeout, in seconds, for borrowed connections. 0 denotes no limit. spring.jta.atomikos.connectionfactory.unique-resource-name=jmsConnectionFactory # The unique name used to identify the resource during recovery. spring.jta.atomikos.datasource.borrow-connection-timeout=30 # Timeout, in seconds, for borrowing connections from the pool. spring.jta.atomikos.datasource.default-isolation-level= # Default isolation level of connections provided by the pool. spring.jta.atomikos.datasource.login-timeout= # Timeout, in seconds, for establishing a database connection. spring.jta.atomikos.datasource.maintenance-interval=60 # The time, in seconds, between runs of the pool's maintenance thread. spring.jta.atomikos.datasource.max-idle-time=60 # The time, in seconds, after which connections are cleaned up from the pool. spring.jta.atomikos.datasource.max-lifetime=0 # The time, in seconds, that a connection can be pooled for before being destroyed. 0 denotes no limit. spring.jta.atomikos.datasource.max-pool-size=1 # The maximum size of the pool. spring.jta.atomikos.datasource.min-pool-size=1 # The minimum size of the pool. spring.jta.atomikos.datasource.reap-timeout=0 # The reap timeout, in seconds, for borrowed connections. 0 denotes no limit. spring.jta.atomikos.datasource.test-query= # SQL query or statement used to validate a connection before returning it. spring.jta.atomikos.datasource.unique-resource-name=dataSource # The unique name used to identify the resource during recovery. spring.jta.atomikos.properties.checkpoint-interval=500 # Interval between checkpoints. spring.jta.atomikos.properties.console-file-count=1 # Number of debug logs files that can be created. spring.jta.atomikos.properties.console-file-limit=-1 # How many bytes can be stored at most in debug logs files. spring.jta.atomikos.properties.console-file-name=tm.out # Debug logs file name. spring.jta.atomikos.properties.console-log-level= # Console log level. spring.jta.atomikos.properties.default-jta-timeout=10000 # Default timeout for JTA transactions. spring.jta.atomikos.properties.enable-logging=true # Enable disk logging. spring.jta.atomikos.properties.force-shutdown-on-vm-exit=false # Specify if a VM shutdown should trigger forced shutdown of the transaction core. spring.jta.atomikos.properties.log-base-dir= # Directory in which the log files should be stored. spring.jta.atomikos.properties.log-base-name=tmlog # Transactions log file base name. spring.jta.atomikos.properties.max-actives=50 # Maximum number of active transactions. spring.jta.atomikos.properties.max-timeout=300000 # Maximum timeout (in milliseconds) that can be allowed for transactions. spring.jta.atomikos.properties.output-dir= # Directory in which to store the debug log files. spring.jta.atomikos.properties.serial-jta-transactions=true # Specify if sub-transactions should be joined when possible. spring.jta.atomikos.properties.service= # Transaction manager implementation that should be started. spring.jta.atomikos.properties.threaded-two-phase-commit=true # Use different (and concurrent) threads for two-phase commit on the participating resources. spring.jta.atomikos.properties.transaction-manager-unique-name= # Transaction manager's unique name. # BITRONIX spring.jta.bitronix.connectionfactory.acquire-increment=1 # Number of connections to create when growing the pool. spring.jta.bitronix.connectionfactory.acquisition-interval=1 # Time, in seconds, to wait before trying to acquire a connection again after an invalid connection was acquired. spring.jta.bitronix.connectionfactory.acquisition-timeout=30 # Timeout, in seconds, for acquiring connections from the pool. spring.jta.bitronix.connectionfactory.allow-local-transactions=true # Whether or not the transaction manager should allow mixing XA and non-XA transactions. spring.jta.bitronix.connectionfactory.apply-transaction-timeout=false # Whether or not the transaction timeout should be set on the XAResource when it is enlisted. spring.jta.bitronix.connectionfactory.automatic-enlisting-enabled=true # Whether or not resources should be enlisted and delisted automatically. spring.jta.bitronix.connectionfactory.cache-producers-consumers=true # Whether or not produces and consumers should be cached. spring.jta.bitronix.connectionfactory.defer-connection-release=true # Whether or not the provider can run many transactions on the same connection and supports transaction interleaving. spring.jta.bitronix.connectionfactory.ignore-recovery-failures=false # Whether or not recovery failures should be ignored. spring.jta.bitronix.connectionfactory.max-idle-time=60 # The time, in seconds, after which connections are cleaned up from the pool. spring.jta.bitronix.connectionfactory.max-pool-size=10 # The maximum size of the pool. 0 denotes no limit. spring.jta.bitronix.connectionfactory.min-pool-size=0 # The minimum size of the pool. spring.jta.bitronix.connectionfactory.password= # The password to use to connect to the JMS provider. spring.jta.bitronix.connectionfactory.share-transaction-connections=false # Whether or not connections in the ACCESSIBLE state can be shared within the context of a transaction. spring.jta.bitronix.connectionfactory.test-connections=true # Whether or not connections should be tested when acquired from the pool. spring.jta.bitronix.connectionfactory.two-pc-ordering-position=1 # The position that this resource should take during two-phase commit (always first is Integer.MIN_VALUE, always last is Integer.MAX_VALUE). spring.jta.bitronix.connectionfactory.unique-name=jmsConnectionFactory # The unique name used to identify the resource during recovery. spring.jta.bitronix.connectionfactory.use-tm-join=true Whether or not TMJOIN should be used when starting XAResources. spring.jta.bitronix.connectionfactory.user= # The user to use to connect to the JMS provider. spring.jta.bitronix.datasource.acquire-increment=1 # Number of connections to create when growing the pool. spring.jta.bitronix.datasource.acquisition-interval=1 # Time, in seconds, to wait before trying to acquire a connection again after an invalid connection was acquired. spring.jta.bitronix.datasource.acquisition-timeout=30 # Timeout, in seconds, for acquiring connections from the pool. spring.jta.bitronix.datasource.allow-local-transactions=true # Whether or not the transaction manager should allow mixing XA and non-XA transactions. spring.jta.bitronix.datasource.apply-transaction-timeout=false # Whether or not the transaction timeout should be set on the XAResource when it is enlisted. spring.jta.bitronix.datasource.automatic-enlisting-enabled=true # Whether or not resources should be enlisted and delisted automatically. spring.jta.bitronix.datasource.cursor-holdability= # The default cursor holdability for connections. spring.jta.bitronix.datasource.defer-connection-release=true # Whether or not the database can run many transactions on the same connection and supports transaction interleaving. spring.jta.bitronix.datasource.enable-jdbc4-connection-test= # Whether or not Connection.isValid() is called when acquiring a connection from the pool. spring.jta.bitronix.datasource.ignore-recovery-failures=false # Whether or not recovery failures should be ignored. spring.jta.bitronix.datasource.isolation-level= # The default isolation level for connections. spring.jta.bitronix.datasource.local-auto-commit= # The default auto-commit mode for local transactions. spring.jta.bitronix.datasource.login-timeout= # Timeout, in seconds, for establishing a database connection. spring.jta.bitronix.datasource.max-idle-time=60 # The time, in seconds, after which connections are cleaned up from the pool. spring.jta.bitronix.datasource.max-pool-size=10 # The maximum size of the pool. 0 denotes no limit. spring.jta.bitronix.datasource.min-pool-size=0 # The minimum size of the pool. spring.jta.bitronix.datasource.prepared-statement-cache-size=0 # The target size of the prepared statement cache. 0 disables the cache. spring.jta.bitronix.datasource.share-transaction-connections=false # Whether or not connections in the ACCESSIBLE state can be shared within the context of a transaction. spring.jta.bitronix.datasource.test-query= # SQL query or statement used to validate a connection before returning it. spring.jta.bitronix.datasource.two-pc-ordering-position=1 # The position that this resource should take during two-phase commit (always first is Integer.MIN_VALUE, always last is Integer.MAX_VALUE). spring.jta.bitronix.datasource.unique-name=dataSource # The unique name used to identify the resource during recovery. spring.jta.bitronix.datasource.use-tm-join=true Whether or not TMJOIN should be used when starting XAResources. spring.jta.bitronix.properties.allow-multiple-lrc=false # Allow multiple LRC resources to be enlisted into the same transaction. spring.jta.bitronix.properties.asynchronous2-pc=false # Enable asynchronously execution of two phase commit. spring.jta.bitronix.properties.background-recovery-interval-seconds=60 # Interval in seconds at which to run the recovery process in the background. spring.jta.bitronix.properties.current-node-only-recovery=true # Recover only the current node. spring.jta.bitronix.properties.debug-zero-resource-transaction=false # Log the creation and commit call stacks of transactions executed without a single enlisted resource. spring.jta.bitronix.properties.default-transaction-timeout=60 # Default transaction timeout in seconds. spring.jta.bitronix.properties.disable-jmx=false # Enable JMX support. spring.jta.bitronix.properties.exception-analyzer= # Set the fully qualified name of the exception analyzer implementation to use. spring.jta.bitronix.properties.filter-log-status=false # Enable filtering of logs so that only mandatory logs are written. spring.jta.bitronix.properties.force-batching-enabled=true # Set if disk forces are batched. spring.jta.bitronix.properties.forced-write-enabled=true # Set if logs are forced to disk. spring.jta.bitronix.properties.graceful-shutdown-interval=60 # Maximum amount of seconds the TM will wait for transactions to get done before aborting them at shutdown time. spring.jta.bitronix.properties.jndi-transaction-synchronization-registry-name= # JNDI name of the TransactionSynchronizationRegistry. spring.jta.bitronix.properties.jndi-user-transaction-name= # JNDI name of the UserTransaction. spring.jta.bitronix.properties.journal=disk # Name of the journal. Can be 'disk', 'null' or a class name. spring.jta.bitronix.properties.log-part1-filename=btm1.tlog # Name of the first fragment of the journal. spring.jta.bitronix.properties.log-part2-filename=btm2.tlog # Name of the second fragment of the journal. spring.jta.bitronix.properties.max-log-size-in-mb=2 # Maximum size in megabytes of the journal fragments. spring.jta.bitronix.properties.resource-configuration-filename= # ResourceLoader configuration file name. spring.jta.bitronix.properties.server-id= # ASCII ID that must uniquely identify this TM instance. Default to the machine's IP address. spring.jta.bitronix.properties.skip-corrupted-logs=false # Skip corrupted transactions log entries. spring.jta.bitronix.properties.warn-about-zero-resource-transaction=true # Log a warning for transactions executed without a single enlisted resource. # NARAYANA (NarayanaProperties) spring.jta.narayana.default-timeout=60 # Transaction timeout in seconds. spring.jta.narayana.expiry-scanners=com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner # Comma-separated list of expiry scanners. spring.jta.narayana.log-dir= # Transaction object store directory. spring.jta.narayana.one-phase-commit=true # Enable one phase commit optimisation. spring.jta.narayana.periodic-recovery-period=120 # Interval in which periodic recovery scans are performed in seconds. spring.jta.narayana.recovery-backoff-period=10 # Back off period between first and second phases of the recovery scan in seconds. spring.jta.narayana.recovery-db-pass= # Database password to be used by recovery manager. spring.jta.narayana.recovery-db-user= # Database username to be used by recovery manager. spring.jta.narayana.recovery-jms-pass= # JMS password to be used by recovery manager. spring.jta.narayana.recovery-jms-user= # JMS username to be used by recovery manager. spring.jta.narayana.recovery-modules= # Comma-separated list of recovery modules. spring.jta.narayana.transaction-manager-id=1 # Unique transaction manager id. spring.jta.narayana.xa-resource-orphan-filters= # Comma-separated list of orphan filters. # EMBEDDED MONGODB (EmbeddedMongoProperties) spring.mongodb.embedded.features=SYNC_DELAY # Comma-separated list of features to enable. spring.mongodb.embedded.storage.databaseDir= # Directory used for data storage. spring.mongodb.embedded.storage.oplogSize= # Maximum size of the oplog in megabytes. spring.mongodb.embedded.storage.replSetName= # Name of the replica set. spring.mongodb.embedded.version=2.6.10 # Version of Mongo to use. # REDIS (RedisProperties) spring.redis.cluster.max-redirects= # Maximum number of redirects to follow when executing commands across the cluster. spring.redis.cluster.nodes= # Comma-separated list of "host:port" pairs to bootstrap from. spring.redis.database=0 # Database index used by the connection factory. spring.redis.host=localhost # Redis server host. spring.redis.password= # Login password of the redis server. spring.redis.pool.max-active=8 # Max number of connections that can be allocated by the pool at a given time. Use a negative value for no limit. spring.redis.pool.max-idle=8 # Max number of "idle" connections in the pool. Use a negative value to indicate an unlimited number of idle connections. spring.redis.pool.max-wait=-1 # Maximum amount of time (in milliseconds) a connection allocation should block before throwing an exception when the pool is exhausted. Use a negative value to block indefinitely. spring.redis.pool.min-idle=0 # Target for the minimum number of idle connections to maintain in the pool. This setting only has an effect if it is positive. spring.redis.port=6379 # Redis server port. spring.redis.sentinel.master= # Name of Redis server. spring.redis.sentinel.nodes= # Comma-separated list of host:port pairs. spring.redis.timeout=0 # Connection timeout in milliseconds. # ---------------------------------------- # INTEGRATION PROPERTIES # ---------------------------------------- # ACTIVEMQ (ActiveMQProperties) spring.activemq.broker-url= # URL of the ActiveMQ broker. Auto-generated by default. For instance `tcp://localhost:61616` spring.activemq.in-memory=true # Specify if the default broker URL should be in memory. Ignored if an explicit broker has been specified. spring.activemq.password= # Login password of the broker. spring.activemq.user= # Login user of the broker. spring.activemq.packages.trust-all=false # Trust all packages. spring.activemq.packages.trusted= # Comma-separated list of specific packages to trust (when not trusting all packages). spring.activemq.pool.configuration.*= # See PooledConnectionFactory. spring.activemq.pool.enabled=false # Whether a PooledConnectionFactory should be created instead of a regular ConnectionFactory. spring.activemq.pool.expiry-timeout=0 # Connection expiration timeout in milliseconds. spring.activemq.pool.idle-timeout=30000 # Connection idle timeout in milliseconds. spring.activemq.pool.max-connections=1 # Maximum number of pooled connections. # ARTEMIS (ArtemisProperties) spring.artemis.embedded.cluster-password= # Cluster password. Randomly generated on startup by default. spring.artemis.embedded.data-directory= # Journal file directory. Not necessary if persistence is turned off. spring.artemis.embedded.enabled=true # Enable embedded mode if the Artemis server APIs are available. spring.artemis.embedded.persistent=false # Enable persistent store. spring.artemis.embedded.queues= # Comma-separated list of queues to create on startup. spring.artemis.embedded.server-id= # Server id. By default, an auto-incremented counter is used. spring.artemis.embedded.topics= # Comma-separated list of topics to create on startup. spring.artemis.host=localhost # Artemis broker host. spring.artemis.mode= # Artemis deployment mode, auto-detected by default. Can be explicitly set to "native" or "embedded". spring.artemis.password= # Login password of the broker. spring.artemis.port=61616 # Artemis broker port. spring.artemis.user= # Login user of the broker. # SPRING BATCH (BatchProperties) spring.batch.initializer.enabled=true # Create the required batch tables on startup if necessary. spring.batch.job.enabled=true # Execute all Spring Batch jobs in the context on startup. spring.batch.job.names= # Comma-separated list of job names to execute on startup (For instance `job1,job2`). By default, all Jobs found in the context are executed. spring.batch.schema=classpath:org/springframework/batch/core/schema-@@platform@@.sql # Path to the SQL file to use to initialize the database schema. spring.batch.table-prefix= # Table prefix for all the batch meta-data tables. # HORNETQ (HornetQProperties) spring.hornetq.embedded.cluster-password= # Cluster password. Randomly generated on startup by default. spring.hornetq.embedded.data-directory= # Journal file directory. Not necessary if persistence is turned off. spring.hornetq.embedded.enabled=true # Enable embedded mode if the HornetQ server APIs are available. spring.hornetq.embedded.persistent=false # Enable persistent store. spring.hornetq.embedded.queues= # Comma-separated list of queues to create on startup. spring.hornetq.embedded.server-id= # Server id. By default, an auto-incremented counter is used. spring.hornetq.embedded.topics= # Comma-separated list of topics to create on startup. spring.hornetq.host=localhost # HornetQ broker host. spring.hornetq.mode= # HornetQ deployment mode, auto-detected by default. Can be explicitly set to "native" or "embedded". spring.hornetq.password= # Login password of the broker. spring.hornetq.port=5445 # HornetQ broker port. spring.hornetq.user= # Login user of the broker. # JMS (JmsProperties) spring.jms.jndi-name= # Connection factory JNDI name. When set, takes precedence to others connection factory auto-configurations. spring.jms.listener.acknowledge-mode= # Acknowledge mode of the container. By default, the listener is transacted with automatic acknowledgment. spring.jms.listener.auto-startup=true # Start the container automatically on startup. spring.jms.listener.concurrency= # Minimum number of concurrent consumers. spring.jms.listener.max-concurrency= # Maximum number of concurrent consumers. spring.jms.pub-sub-domain=false # Specify if the default destination type is topic. # RABBIT (RabbitProperties) spring.rabbitmq.addresses= # Comma-separated list of addresses to which the client should connect. spring.rabbitmq.cache.channel.checkout-timeout= # Number of milliseconds to wait to obtain a channel if the cache size has been reached. spring.rabbitmq.cache.channel.size= # Number of channels to retain in the cache. spring.rabbitmq.cache.connection.mode=CHANNEL # Connection factory cache mode. spring.rabbitmq.cache.connection.size= # Number of connections to cache. spring.rabbitmq.connection-timeout= # Connection timeout, in milliseconds; zero for infinite. spring.rabbitmq.dynamic=true # Create an AmqpAdmin bean. spring.rabbitmq.host=localhost # RabbitMQ host. spring.rabbitmq.listener.acknowledge-mode= # Acknowledge mode of container. spring.rabbitmq.listener.auto-startup=true # Start the container automatically on startup. spring.rabbitmq.listener.concurrency= # Minimum number of consumers. spring.rabbitmq.listener.default-requeue-rejected= # Whether or not to requeue delivery failures; default `true`. spring.rabbitmq.listener.max-concurrency= # Maximum number of consumers. spring.rabbitmq.listener.prefetch= # Number of messages to be handled in a single request. It should be greater than or equal to the transaction size (if used). spring.rabbitmq.listener.retry.enabled=false # Whether or not publishing retries are enabled. spring.rabbitmq.listener.retry.initial-interval=1000 # Interval between the first and second attempt to deliver a message. spring.rabbitmq.listener.retry.max-attempts=3 # Maximum number of attempts to deliver a message. spring.rabbitmq.listener.retry.max-interval=10000 # Maximum number of attempts to deliver a message. spring.rabbitmq.listener.retry.multiplier=1.0 # A multiplier to apply to the previous delivery retry interval. spring.rabbitmq.listener.retry.stateless=true # Whether or not retry is stateless or stateful. spring.rabbitmq.listener.transaction-size= # Number of messages to be processed in a transaction. For best results it should be less than or equal to the prefetch count. spring.rabbitmq.password= # Login to authenticate against the broker. spring.rabbitmq.port=5672 # RabbitMQ port. spring.rabbitmq.publisher-confirms=false # Enable publisher confirms. spring.rabbitmq.publisher-returns=false # Enable publisher returns. spring.rabbitmq.requested-heartbeat= # Requested heartbeat timeout, in seconds; zero for none. spring.rabbitmq.ssl.enabled=false # Enable SSL support. spring.rabbitmq.ssl.key-store= # Path to the key store that holds the SSL certificate. spring.rabbitmq.ssl.key-store-password= # Password used to access the key store. spring.rabbitmq.ssl.trust-store= # Trust store that holds SSL certificates. spring.rabbitmq.ssl.trust-store-password= # Password used to access the trust store. spring.rabbitmq.ssl.algorithm= # SSL algorithm to use. By default configure by the rabbit client library. spring.rabbitmq.template.mandatory=false # Enable mandatory messages. spring.rabbitmq.template.receive-timeout=0 # Timeout for `receive()` methods. spring.rabbitmq.template.reply-timeout=5000 # Timeout for `sendAndReceive()` methods. spring.rabbitmq.template.retry.enabled=false # Set to true to enable retries in the `RabbitTemplate`. spring.rabbitmq.template.retry.initial-interval=1000 # Interval between the first and second attempt to publish a message. spring.rabbitmq.template.retry.max-attempts=3 # Maximum number of attempts to publish a message. spring.rabbitmq.template.retry.max-interval=10000 # Maximum number of attempts to publish a message. spring.rabbitmq.template.retry.multiplier=1.0 # A multiplier to apply to the previous publishing retry interval. spring.rabbitmq.username= # Login user to authenticate to the broker. spring.rabbitmq.virtual-host= # Virtual host to use when connecting to the broker. # ---------------------------------------- # ACTUATOR PROPERTIES # ---------------------------------------- # ENDPOINTS (AbstractEndpoint subclasses) endpoints.enabled=true # Enable endpoints. endpoints.sensitive= # Default endpoint sensitive setting. endpoints.actuator.enabled=true # Enable the endpoint. endpoints.actuator.path= # Endpoint URL path. endpoints.actuator.sensitive=false # Enable security on the endpoint. endpoints.autoconfig.enabled= # Enable the endpoint. endpoints.autoconfig.id= # Endpoint identifier. endpoints.autoconfig.path= # Endpoint path. endpoints.autoconfig.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.beans.enabled= # Enable the endpoint. endpoints.beans.id= # Endpoint identifier. endpoints.beans.path= # Endpoint path. endpoints.beans.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.configprops.enabled= # Enable the endpoint. endpoints.configprops.id= # Endpoint identifier. endpoints.configprops.keys-to-sanitize=password,secret,key,token,.*credentials.*,vcap_services # Keys that should be sanitized. Keys can be simple strings that the property ends with or regex expressions. endpoints.configprops.path= # Endpoint path. endpoints.configprops.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.docs.curies.enabled=false # Enable the curie generation. endpoints.docs.enabled=true # Enable actuator docs endpoint. endpoints.docs.path=/docs # endpoints.docs.sensitive=false # endpoints.dump.enabled= # Enable the endpoint. endpoints.dump.id= # Endpoint identifier. endpoints.dump.path= # Endpoint path. endpoints.dump.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.env.enabled= # Enable the endpoint. endpoints.env.id= # Endpoint identifier. endpoints.env.keys-to-sanitize=password,secret,key,token,.*credentials.*,vcap_services # Keys that should be sanitized. Keys can be simple strings that the property ends with or regex expressions. endpoints.env.path= # Endpoint path. endpoints.env.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.flyway.enabled= # Enable the endpoint. endpoints.flyway.id= # Endpoint identifier. endpoints.flyway.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.health.enabled= # Enable the endpoint. endpoints.health.id= # Endpoint identifier. endpoints.health.mapping.*= # Mapping of health statuses to HttpStatus codes. By default, registered health statuses map to sensible defaults (i.e. UP maps to 200). endpoints.health.path= # Endpoint path. endpoints.health.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.health.time-to-live=1000 # Time to live for cached result, in milliseconds. endpoints.heapdump.enabled= # Enable the endpoint. endpoints.heapdump.path= # Endpoint path. endpoints.heapdump.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.info.enabled= # Enable the endpoint. endpoints.info.id= # Endpoint identifier. endpoints.info.path= # Endpoint path. endpoints.info.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.jolokia.enabled=true # Enable Jolokia endpoint. endpoints.jolokia.path=/jolokia # Endpoint URL path. endpoints.jolokia.sensitive=true # Enable security on the endpoint. endpoints.liquibase.enabled= # Enable the endpoint. endpoints.liquibase.id= # Endpoint identifier. endpoints.liquibase.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.logfile.enabled=true # Enable the endpoint. endpoints.logfile.external-file= # External Logfile to be accessed. endpoints.logfile.path=/logfile # Endpoint URL path. endpoints.logfile.sensitive=true # Enable security on the endpoint. endpoints.mappings.enabled= # Enable the endpoint. endpoints.mappings.id= # Endpoint identifier. endpoints.mappings.path= # Endpoint path. endpoints.mappings.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.metrics.enabled= # Enable the endpoint. endpoints.metrics.filter.enabled=true # Enable the metrics servlet filter. endpoints.metrics.filter.gauge-submissions=merged # Http filter gauge submissions (merged, per-http-method) endpoints.metrics.filter.counter-submissions=merged # Http filter counter submissions (merged, per-http-method) endpoints.metrics.id= # Endpoint identifier. endpoints.metrics.path= # Endpoint path. endpoints.metrics.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.shutdown.enabled= # Enable the endpoint. endpoints.shutdown.id= # Endpoint identifier. endpoints.shutdown.path= # Endpoint path. endpoints.shutdown.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.trace.enabled= # Enable the endpoint. endpoints.trace.id= # Endpoint identifier. endpoints.trace.path= # Endpoint path. endpoints.trace.sensitive= # Mark if the endpoint exposes sensitive information. # ENDPOINTS CORS CONFIGURATION (EndpointCorsProperties) endpoints.cors.allow-credentials= # Set whether credentials are supported. When not set, credentials are not supported. endpoints.cors.allowed-headers= # Comma-separated list of headers to allow in a request. '*' allows all headers. endpoints.cors.allowed-methods=GET # Comma-separated list of methods to allow. '*' allows all methods. endpoints.cors.allowed-origins= # Comma-separated list of origins to allow. '*' allows all origins. When not set, CORS support is disabled. endpoints.cors.exposed-headers= # Comma-separated list of headers to include in a response. endpoints.cors.max-age=1800 # How long, in seconds, the response from a pre-flight request can be cached by clients. # JMX ENDPOINT (EndpointMBeanExportProperties) endpoints.jmx.domain= # JMX domain name. Initialized with the value of 'spring.jmx.default-domain' if set. endpoints.jmx.enabled=true # Enable JMX export of all endpoints. endpoints.jmx.static-names= # Additional static properties to append to all ObjectNames of MBeans representing Endpoints. endpoints.jmx.unique-names=false # Ensure that ObjectNames are modified in case of conflict. # JOLOKIA (JolokiaProperties) jolokia.config.*= # See Jolokia manual # MANAGEMENT HTTP SERVER (ManagementServerProperties) management.add-application-context-header=true # Add the "X-Application-Context" HTTP header in each response. management.address= # Network address that the management endpoints should bind to. management.context-path= # Management endpoint context-path. For instance `/actuator` management.port= # Management endpoint HTTP port. Uses the same port as the application by default. Configure a different port to use management-specific SSL. management.security.enabled=true # Enable security. management.security.roles=ADMIN # Comma-separated list of roles that can access the management endpoint. management.security.sessions=stateless # Session creating policy to use (always, never, if_required, stateless). management.ssl.ciphers= # Supported SSL ciphers. Requires a custom management.port. management.ssl.client-auth= # Whether client authentication is wanted ("want") or needed ("need"). Requires a trust store. Requires a custom management.port. management.ssl.enabled= # Enable SSL support. Requires a custom management.port. management.ssl.enabled-protocols= # Enabled SSL protocols. Requires a custom management.port. management.ssl.key-alias= # Alias that identifies the key in the key store. Requires a custom management.port. management.ssl.key-password= # Password used to access the key in the key store. Requires a custom management.port. management.ssl.key-store= # Path to the key store that holds the SSL certificate (typically a jks file). Requires a custom management.port. management.ssl.key-store-password= # Password used to access the key store. Requires a custom management.port. management.ssl.key-store-provider= # Provider for the key store. Requires a custom management.port. management.ssl.key-store-type= # Type of the key store. Requires a custom management.port. management.ssl.protocol=TLS # SSL protocol to use. Requires a custom management.port. management.ssl.trust-store= # Trust store that holds SSL certificates. Requires a custom management.port. management.ssl.trust-store-password= # Password used to access the trust store. Requires a custom management.port. management.ssl.trust-store-provider= # Provider for the trust store. Requires a custom management.port. management.ssl.trust-store-type= # Type of the trust store. Requires a custom management.port. # HEALTH INDICATORS (previously health.*) management.health.db.enabled=true # Enable database health check. management.health.defaults.enabled=true # Enable default health indicators. management.health.diskspace.enabled=true # Enable disk space health check. management.health.diskspace.path= # Path used to compute the available disk space. management.health.diskspace.threshold=0 # Minimum disk space that should be available, in bytes. management.health.elasticsearch.enabled=true # Enable elasticsearch health check. management.health.elasticsearch.indices= # Comma-separated index names. management.health.elasticsearch.response-timeout=100 # The time, in milliseconds, to wait for a response from the cluster. management.health.jms.enabled=true # Enable JMS health check. management.health.mail.enabled=true # Enable Mail health check. management.health.mongo.enabled=true # Enable MongoDB health check. management.health.rabbit.enabled=true # Enable RabbitMQ health check. management.health.redis.enabled=true # Enable Redis health check. management.health.solr.enabled=true # Enable Solr health check. management.health.status.order=DOWN, OUT_OF_SERVICE, UNKNOWN, UP # Comma-separated list of health statuses in order of severity. # INFO CONTRIBUTORS (InfoContributorProperties) management.info.build.enabled=true # Enable build info. management.info.defaults.enabled=true # Enable default info contributors. management.info.env.enabled=true # Enable environment info. management.info.git.enabled=true # Enable git info. management.info.git.mode=simple # Mode to use to expose git information. # REMOTE SHELL (ShellProperties) management.shell.auth.type=simple # Authentication type. Auto-detected according to the environment. management.shell.auth.jaas.domain=my-domain # JAAS domain. management.shell.auth.key.path= # Path to the authentication key. This should point to a valid ".pem" file. management.shell.auth.simple.user.name=user # Login user. management.shell.auth.simple.user.password= # Login password. management.shell.auth.spring.roles=ADMIN # Comma-separated list of required roles to login to the CRaSH console. management.shell.command-path-patterns=classpath*:/commands/**,classpath*:/crash/commands/** # Patterns to use to look for commands. management.shell.command-refresh-interval=-1 # Scan for changes and update the command if necessary (in seconds). management.shell.config-path-patterns=classpath*:/crash/* # Patterns to use to look for configurations. management.shell.disabled-commands=jpa*,jdbc*,jndi* # Comma-separated list of commands to disable. management.shell.disabled-plugins= # Comma-separated list of plugins to disable. Certain plugins are disabled by default based on the environment. management.shell.ssh.auth-timeout = # Number of milliseconds after user will be prompted to login again. management.shell.ssh.enabled=true # Enable CRaSH SSH support. management.shell.ssh.idle-timeout = # Number of milliseconds after which unused connections are closed. management.shell.ssh.key-path= # Path to the SSH server key. management.shell.ssh.port=2000 # SSH port. management.shell.telnet.enabled=false # Enable CRaSH telnet support. Enabled by default if the TelnetPlugin is available. management.shell.telnet.port=5000 # Telnet port. # TRACING (TraceProperties) management.trace.include=request-headers,response-headers,cookies,errors # Items to be included in the trace. # METRICS EXPORT (MetricExportProperties) spring.metrics.export.aggregate.key-pattern= # Pattern that tells the aggregator what to do with the keys from the source repository. spring.metrics.export.aggregate.prefix= # Prefix for global repository if active. spring.metrics.export.delay-millis=5000 # Delay in milliseconds between export ticks. Metrics are exported to external sources on a schedule with this delay. spring.metrics.export.enabled=true # Flag to enable metric export (assuming a MetricWriter is available). spring.metrics.export.excludes= # List of patterns for metric names to exclude. Applied after the includes. spring.metrics.export.includes= # List of patterns for metric names to include. spring.metrics.export.redis.key=keys.spring.metrics # Key for redis repository export (if active). spring.metrics.export.redis.prefix=spring.metrics # Prefix for redis repository if active. spring.metrics.export.send-latest= # Flag to switch off any available optimizations based on not exporting unchanged metric values. spring.metrics.export.statsd.host= # Host of a statsd server to receive exported metrics. spring.metrics.export.statsd.port=8125 # Port of a statsd server to receive exported metrics. spring.metrics.export.statsd.prefix= # Prefix for statsd exported metrics. spring.metrics.export.triggers.*= # Specific trigger properties per MetricWriter bean name. # ---------------------------------------- # DEVTOOLS PROPERTIES # ---------------------------------------- # DEVTOOLS (DevToolsProperties) spring.devtools.livereload.enabled=true # Enable a livereload.com compatible server. spring.devtools.livereload.port=35729 # Server port. spring.devtools.restart.additional-exclude= # Additional patterns that should be excluded from triggering a full restart. spring.devtools.restart.additional-paths= # Additional paths to watch for changes. spring.devtools.restart.enabled=true # Enable automatic restart. spring.devtools.restart.exclude=META-INF/maven/**,META-INF/resources/**,resources/**,static/**,public/**,templates/**,**/*Test.class,**/*Tests.class,git.properties # Patterns that should be excluded from triggering a full restart. spring.devtools.restart.poll-interval=1000 # Amount of time (in milliseconds) to wait between polling for classpath changes. spring.devtools.restart.quiet-period=400 # Amount of quiet time (in milliseconds) required without any classpath changes before a restart is triggered. spring.devtools.restart.trigger-file= # Name of a specific file that when changed will trigger the restart check. If not specified any classpath file change will trigger the restart. # REMOTE DEVTOOLS (RemoteDevToolsProperties) spring.devtools.remote.context-path=/.~~spring-boot!~ # Context path used to handle the remote connection. spring.devtools.remote.debug.enabled=true # Enable remote debug support. spring.devtools.remote.debug.local-port=8000 # Local remote debug server port. spring.devtools.remote.proxy.host= # The host of the proxy to use to connect to the remote application. spring.devtools.remote.proxy.port= # The port of the proxy to use to connect to the remote application. spring.devtools.remote.restart.enabled=true # Enable remote restart. spring.devtools.remote.secret= # A shared secret required to establish a connection (required to enable remote support). spring.devtools.remote.secret-header-name=X-AUTH-TOKEN # HTTP header used to transfer the shared secret.
-------------- HEX CONVERSION ----------------
CREATE OR REPLACE FUNCTION SCP.DEC_STR (
I_OWNER IN VARCHAR2,
I_TABLE IN VARCHAR2,
I_COLUMN IN VARCHAR2,
I_DATA IN VARCHAR2
)
RETURN VARCHAR2 PARALLEL_ENABLE DETERMINISTIC IS
BEGIN
IF I_DATA IS NULL THEN
RETURN NULL;
END IF;
RETURN UTL_RAW.CAST_TO_VARCHAR2(I_DATA);
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR (-20010, TO_CHAR(SQLCODE) || ' ' || SUBSTR(SQLERRM, 11, 1024) );
RETURN NULL;
END;
-------------- HEX CONVERSION ----------------
CREATE OR REPLACE FUNCTION SCP.ENC_STR (
I_OWNER IN VARCHAR2,
I_TABLE IN VARCHAR2,
I_COLUMN IN VARCHAR2,
I_DATA IN VARCHAR2
)
RETURN VARCHAR2 PARALLEL_ENABLE DETERMINISTIC IS
BEGIN
IF I_DATA IS NULL THEN
RETURN NULL;
END IF;
RETURN UTL_RAW.CAST_TO_RAW(I_DATA);
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR (-20010, TO_CHAR(SQLCODE) || ' ' || SUBSTR(SQLERRM, 11, 1024) );
RETURN NULL;
END;
1 2 3 4 5 6 7 | ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject(ExcelConstant.EXCEL_TITLE, excelTitle); modelAndView.addObject(ExcelConstant.EXCEL_SHEET_NAME, excelSheetName); modelAndView.addObject(ExcelConstant.EXCEL_FILE_NAME, excelTitle); modelAndView.addObject(ExcelConstant.EXCEL_DATA_LIST, dataMapList); modelAndView.setViewName("excelDownloadView"); | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | package kr.go.safepeople.config.component; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import kr.go.safepeople.config.exception.SafePeopleException; import kr.go.safepeople.config.util.DataMap; import org.apache.poi.hssf.usermodel.HSSFFont; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFFont; import org.springframework.stereotype.Component; import org.springframework.web.servlet.view.AbstractView; @Component("excelDownloadView") public class ExcelDownloadView extends AbstractView{ public ExcelDownloadView() { // TODO Auto-generated constructor stub setContentType("application/download; charset=utf-8"); } @Override protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws SafePeopleException { // TODO Auto-generated method stub try{ String excelFileName = (String)model.get(ExcelConstant.EXCEL_FILE_NAME); StringBuffer fileName = new StringBuffer(); ServletOutputStream out = response.getOutputStream(); fileName.append(excelFileName); fileName.append("_"); fileName.append(currentDate("yyyyMMdd_HHmmss")); List<DataMap> excelDataList = (List<DataMap>)model.get(ExcelConstant.EXCEL_DATA_LIST); if(excelDataList.size()==0){ out.print("NODATA"); }else{ Workbook workbook = new SXSSFWorkbook(500); buildExcelDocument(model, workbook); fileName.append(".xlsx"); setResponse(request,response,fileName.toString()); workbook.write(out); } if(out != null){out.close();} } catch (Exception e) { logger.debug(e.getMessage(), e); throw new SafePeopleException(e); } } private void setResponse(HttpServletRequest request, HttpServletResponse response, String fileName) throws UnsupportedEncodingException{ String userAgent = request.getHeader("User-Agent"); String downFileName = ""; if(fileName!=null){ downFileName = fileName; } if (userAgent.indexOf("MSIE 5.5") > -1) { // MS IE 5.5 이하 response.setHeader("Content-Disposition", "filename=" + URLEncoder.encode(downFileName, "UTF-8").replaceAll("\\+", "\\ ") + ";"); } else if (userAgent.indexOf("MSIE") > -1) { // MS IE (보통은 6.x 이상 가정) response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(downFileName, "UTF-8").replaceAll("\\+", "\\ ") + ";"); } else if (userAgent.indexOf("Trident") > -1) { // MS IE 11 response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(downFileName, "UTF-8").replaceAll("\\+", "\\ ") + ";"); } else { // 모질라나 오페라 downFileName = URLEncoder.encode(downFileName,"UTF-8"); response.setHeader("Content-Disposition", "attachment; filename=\""+downFileName.replaceAll("\\+", "\\ ")+"\";"); } } private String currentDate(String format){ SimpleDateFormat sd = new SimpleDateFormat(format, Locale.KOREA); return sd.format(new Date()); } private void buildExcelDocument(Map<String, Object> model, Workbook workbook) { // TODO Auto-generated method stub // init String excelTitle = ExcelConstant.EXCEL_TITLE_EMPTY; if(model.get(ExcelConstant.EXCEL_TITLE) != null){ excelTitle = (String)model.get(ExcelConstant.EXCEL_TITLE); } String excelSheetName = ExcelConstant.EXCEL_SHEET_NAME_EMPTY; if(model.get(ExcelConstant.EXCEL_SHEET_NAME) != null){ excelSheetName = (String)model.get(ExcelConstant.EXCEL_SHEET_NAME); } List<DataMap> excelDataList = (List<DataMap>)model.get(ExcelConstant.EXCEL_DATA_LIST); DataMap headerDataMap = excelDataList.get(0); int rowTitleNum = 0; int rowTitleSubNum = 2; int rowHeaderNum = 3; int rowDataNum = 4; String subTitle = "작성일자 :"+currentDate("YYYY년 MM월 d일 HH:mm:ss"); // create title(style,font) XSSFFont titleFont = (XSSFFont)workbook.createFont(); titleFont.setFontHeightInPoints((short)16); titleFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); XSSFCellStyle titleCellStyle = (XSSFCellStyle)workbook.createCellStyle(); titleCellStyle.setBorderRight(XSSFCellStyle.BORDER_THIN); titleCellStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN); titleCellStyle.setBorderTop(XSSFCellStyle.BORDER_THIN); titleCellStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN); titleCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index); titleCellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND); titleCellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER_SELECTION); titleCellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER); titleCellStyle.setFont(titleFont); XSSFCellStyle titleSubCellStyle = (XSSFCellStyle)workbook.createCellStyle(); titleSubCellStyle.setAlignment(XSSFCellStyle.ALIGN_RIGHT); titleSubCellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER); // create hearder(style,font) XSSFFont hearderFont = (XSSFFont)workbook.createFont(); hearderFont.setFontHeightInPoints((short)10); XSSFCellStyle headerCellStyle = (XSSFCellStyle)workbook.createCellStyle(); headerCellStyle.setBorderRight(XSSFCellStyle.BORDER_THIN); headerCellStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN); headerCellStyle.setBorderTop(XSSFCellStyle.BORDER_THIN); headerCellStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN); headerCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index); headerCellStyle.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND); headerCellStyle.setFont(hearderFont); // create data(style,font) XSSFFont dataFont = (XSSFFont)workbook.createFont(); dataFont.setFontHeightInPoints((short)10); XSSFCellStyle dataCellStyle = (XSSFCellStyle)workbook.createCellStyle(); dataCellStyle.setBorderRight(XSSFCellStyle.BORDER_THIN); dataCellStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN); dataCellStyle.setBorderTop(XSSFCellStyle.BORDER_THIN); dataCellStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN); dataCellStyle.setFont(dataFont); // create sheet Sheet sheet = workbook.createSheet(excelSheetName); // create title row Row titleRow = sheet.createRow(rowTitleNum); titleRow.setHeightInPoints(34); Cell titleCell; for(int i = 0 ; i < headerDataMap.keyList().size() ; i++){ titleCell = titleRow.createCell(i); if(i == 0){ titleCell.setCellValue(excelTitle); } titleCell.setCellStyle(titleCellStyle); } sheet.addMergedRegion(new CellRangeAddress(rowTitleNum,rowTitleNum,0,(headerDataMap.keyList().size()-1))); // create titleSub row Row titleSubRow = sheet.createRow(rowTitleSubNum); Cell titleSubCell; for(int i = 0 ; i < headerDataMap.keyList().size() ; i++){ titleSubCell = titleSubRow.createCell(i); if(i == 0){ titleSubCell.setCellValue(subTitle); } titleSubCell.setCellStyle(titleSubCellStyle); } sheet.addMergedRegion(new CellRangeAddress(rowTitleSubNum,rowTitleSubNum,0,(headerDataMap.keyList().size()-1))); // create header row Row headerRow = sheet.createRow(rowHeaderNum); Cell hearderCell; for(int i = 0 ; i < headerDataMap.keyList().size() ; i++){ hearderCell = headerRow.createCell(i); hearderCell.setCellStyle(headerCellStyle); hearderCell.setCellValue((String)headerDataMap.get(i)); } // create data row Row row = null; Cell cell = null; for(int rowIdx = 0 ; rowIdx < excelDataList.size() ; rowIdx++){ row = sheet.createRow(rowDataNum+rowIdx); DataMap rowData = excelDataList.get(rowIdx); for(int cellIdx = 0 ; cellIdx < headerDataMap.keyList().size() ; cellIdx++){ cell = row.createCell(cellIdx); String cellKey = (String)headerDataMap.keyList().get(cellIdx); Object cellData = rowData.get(cellKey); if(cellData instanceof String){ cell.setCellValue((String)cellData); }else if(cellData instanceof Integer){ cell.setCellValue((Integer)cellData); }else if(cellData instanceof Long){ cell.setCellValue((Long)cellData); }else if(cellData instanceof Double){ cell.setCellValue((Double)cellData); }else{ if(cellData != null){ cell.setCellValue(cellData.toString()); } } cell.setCellStyle(dataCellStyle); } } // create cell size for(int i = 0 ; i < headerDataMap.keyList().size() ; i++){ sheet.autoSizeColumn(i,true); } } } | cs |
Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar
Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preemptingStackOverflowError
.
The purpose of slf4j-log4j12 module is to delegate or redirect calls made to an SLF4J logger to log4j. The purpose of the log4j-over-slf4j module is to redirect calls made to a log4j logger to SLF4J. If SLF4J is bound withslf4j-log4j12.jar and log4j-over-slf4j.jar is also present on the class path, a StackOverflowError
will inevitably occur immediately after the first invocation of an SLF4J or a log4j logger.
Here is how the exception might look like:
Exception in thread "main" java.lang.StackOverflowError
at java.util.Hashtable.containsKey(Hashtable.java:306)
at org.apache.log4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:36)
at org.apache.log4j.LogManager.getLogger(LogManager.java:39)
at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:73)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:249)
at org.apache.log4j.Category.<init>(Category.java:53)
at org.apache.log4j.Logger..<init>(Logger.java:35)
at org.apache.log4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:39)
at org.apache.log4j.LogManager.getLogger(LogManager.java:39)
at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:73)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:249)
at org.apache.log4j.Category..<init>(Category.java:53)
at org.apache.log4j.Logger..<init>(Logger.java:35)
at org.apache.log4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:39)
at org.apache.log4j.LogManager.getLogger(LogManager.java:39)
subsequent lines omitted...
SINCE 1.5.11 SLF4J software preempts the inevitable stack overflow error by throwing an exception with details about the actual cause of the problem. This is deemed to be better than leaving the user wondering about the reasons of the StackOverflowError
.
For more background on this topic see Bridging legacy APIs.
-----------------------------------------------
pom.xml hierarchy 에서 의존성 관계 확인후 예외 처리
Problem
CentOS installation fails with the message:
“Unable to read package metadata. This may be due to missing repodata directory. Please ensure that your install tree has been correctly generated”.
Solution 1
Add the corresponding repository server. In case of CentOS 6.5 64bit: http://mirror.centos.org/centos/6.5/os/x86_64/
Solution 2
See the following stackoverflow thread: http://stackoverflow.com/questions/21637068/unable-to-read-package-metadata-this-may-be-due-to-missing-repodata-directory
확인해 보니 mirror 경로가 변경되었다. 괜히 삽질
http://mirror.centos.org/centos/6/os/x86_64/
- 설정 파일 추가.(기존에 해당 파일이 없음)
- 홈디렉토리, listen port 등을 설정할 수 있음.
- $ vi /etc/sysconfig/svnserve
OPTIONS="--threads --root /home/svn"
- /etc/init.d/svnserve 파일을 보면 서비스에 등록하기 위해서 /etc/sysconfig/svnserve 파일이 필요하다는 것을 알 수 있다.
- 이후 service svnserve start|stop|restart 로 구동 가능.
서버 재 부팅시 자동으로 시작하게 만들기.
- 설정확인.
- $ chkconfig --list svnserve
- 설정하기.
- $ chkconfig svnserve on
2.
rpm --import http://mirror.centos.org/centos/6/os/x86_64/RPM-GPG-KEY-CentOS-6
3.