[bs-118], [bs-119]: add UI builder features
* MessageSource created automatically (location spring.messages.basename:messages) * Thymeleaf configured automatically to look for templates in classpath:/templates * Added static resource handlers for classpath:/static and classpath:/ [Fixes #49832165] [bs-118] Support for thymeleaf templates
This commit is contained in:
parent
ceea71fc38
commit
53078c320e
|
|
@ -10,3 +10,4 @@
|
|||
bin
|
||||
build
|
||||
target
|
||||
.springBeans
|
||||
|
|
|
|||
15
pom.xml
15
pom.xml
|
|
@ -309,6 +309,11 @@
|
|||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
<version>1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.javax.persistence</groupId>
|
||||
<artifactId>hibernate-jpa-2.0-api</artifactId>
|
||||
|
|
@ -525,6 +530,16 @@
|
|||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.12</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf-spring3</artifactId>
|
||||
<version>2.0.16</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>nz.net.ultraq.web.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf-layout-dialect</artifactId>
|
||||
<version>1.0.6</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<dependencies>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,2 @@
|
|||
org.springframework.bootstrap.context.annotation.EnableAutoConfiguration=\
|
||||
org.springframework.bootstrap.actuate.autoconfigure.ActuatorAutoConfiguration
|
||||
org.springframework.context.ApplicationContextInitializer=\
|
||||
org.springframework.bootstrap.logging.LoggingInitializer
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
<parent>
|
||||
<artifactId>spring-bootstrap-samples</artifactId>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.5.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-bootstrap-service-sample</artifactId>
|
||||
<artifactId>spring-bootstrap-integration-sample</artifactId>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
|
@ -14,77 +14,6 @@
|
|||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>tomcat</id>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-logging-juli</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>jetty</id>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<version>8.1.9.v20130131</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>javax.servlet</artifactId>
|
||||
<groupId>org.eclipse.jetty.orbit</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-jsp</artifactId>
|
||||
<version>8.1.9.v20130131</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>juli</id>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<version>1.7.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>log4j</id>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>logback</id>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
|
|
@ -128,8 +57,7 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<main.basedir>${project.basedir}/../..</main.basedir>
|
||||
<start-class>org.springframework.bootstrap.sample.service.ServiceBootstrapApplication</start-class>
|
||||
<start-class>org.springframework.bootstrap.sample.service.IntegrationBootstrapApplication</start-class>
|
||||
</properties>
|
||||
</project>
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ public class TradBootstrapApplicationTests {
|
|||
.run(TradBootstrapApplication.class);
|
||||
}
|
||||
});
|
||||
context = future.get(10, TimeUnit.SECONDS);
|
||||
context = future.get(30, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<artifactId>spring-bootstrap-samples</artifactId>
|
||||
<version>0.5.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-bootstrap-ui-sample</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<properties>
|
||||
<m2eclipse.wtp.contextRoot>/</m2eclipse.wtp.contextRoot>
|
||||
<start-class>org.springframework.bootstrap.sample.ui.UiBootstrapApplication</start-class>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-bootstrap</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf-spring3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>nz.net.ultraq.web.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf-layout-dialect</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-logging-juli</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>4.3.1.Final</version>
|
||||
<!-- FIXME: make this optional -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.bootstrap.sample.ui;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class InMemoryMessageRespository implements MessageRepository {
|
||||
|
||||
private static AtomicLong counter = new AtomicLong();
|
||||
private ConcurrentMap<Long, Message> messages = new ConcurrentHashMap<Long, Message>();
|
||||
|
||||
@Override
|
||||
public Iterable<Message> findAll() {
|
||||
return this.messages.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message save(Message message) {
|
||||
Long id = message.getId();
|
||||
if (id == null) {
|
||||
id = counter.incrementAndGet();
|
||||
message.setId(id);
|
||||
}
|
||||
this.messages.put(id, message);
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message findMessage(Long id) {
|
||||
return this.messages.get(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.bootstrap.sample.ui;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
public class Message {
|
||||
|
||||
private Long id;
|
||||
|
||||
@NotEmpty(message = "Message is required.")
|
||||
private String text;
|
||||
|
||||
@NotEmpty(message = "Summary is required.")
|
||||
private String summary;
|
||||
|
||||
private Calendar created = Calendar.getInstance();
|
||||
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Calendar getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
public void setCreated(Calendar created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getSummary() {
|
||||
return this.summary;
|
||||
}
|
||||
|
||||
public void setSummary(String summary) {
|
||||
this.summary = summary;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.bootstrap.sample.ui;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
public interface MessageRepository {
|
||||
|
||||
Iterable<Message> findAll();
|
||||
|
||||
Message save(Message message);
|
||||
|
||||
Message findMessage(Long id);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package org.springframework.bootstrap.sample.ui;
|
||||
|
||||
import org.springframework.bootstrap.SpringApplication;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan
|
||||
public class UiBootstrapApplication {
|
||||
|
||||
@Bean
|
||||
public MessageRepository messageRepository() {
|
||||
return new InMemoryMessageRespository();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Converter<String, Message> messageConverter() {
|
||||
return new Converter<String, Message>() {
|
||||
@Override
|
||||
public Message convert(String id) {
|
||||
return messageRepository().findMessage(Long.valueOf(id));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SpringApplication.run(UiBootstrapApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.bootstrap.sample.ui.mvc;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.bootstrap.sample.ui.Message;
|
||||
import org.springframework.bootstrap.sample.ui.MessageRepository;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
*
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/")
|
||||
public class MessageController {
|
||||
private MessageRepository messageRepository;
|
||||
|
||||
@Autowired
|
||||
public MessageController(MessageRepository messageRepository) {
|
||||
this.messageRepository = messageRepository;
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public ModelAndView list() {
|
||||
Iterable<Message> messages = messageRepository.findAll();
|
||||
return new ModelAndView("messages/list", "messages", messages);
|
||||
}
|
||||
|
||||
@RequestMapping("{id}")
|
||||
public ModelAndView view(@PathVariable("id")
|
||||
Message message) {
|
||||
return new ModelAndView("messages/view", "message", message);
|
||||
}
|
||||
|
||||
@RequestMapping(params = "form", method = RequestMethod.GET)
|
||||
public String createForm(@ModelAttribute
|
||||
Message message) {
|
||||
return "messages/form";
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
public ModelAndView create(@Valid
|
||||
Message message, BindingResult result, RedirectAttributes redirect) {
|
||||
if (result.hasErrors()) {
|
||||
return new ModelAndView("messages/form", "formErrors",
|
||||
result.getAllErrors());
|
||||
}
|
||||
message = messageRepository.save(message);
|
||||
redirect.addFlashAttribute("globalMessage",
|
||||
"Successfully created a new message");
|
||||
return new ModelAndView("redirect:/{message.id}",
|
||||
"message.id", message.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
11
spring-bootstrap-samples/spring-bootstrap-ui-sample/src/main/resources/css/bootstrap.min.css
vendored
Normal file
11
spring-bootstrap-samples/spring-bootstrap-ui-sample/src/main/resources/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
9404
spring-bootstrap-samples/spring-bootstrap-ui-sample/src/main/resources/js/jquery-1.7.2.js
vendored
Normal file
9404
spring-bootstrap-samples/spring-bootstrap-ui-sample/src/main/resources/js/jquery-1.7.2.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1250
spring-bootstrap-samples/spring-bootstrap-ui-sample/src/main/resources/js/jquery.validate.js
vendored
Normal file
1250
spring-bootstrap-samples/spring-bootstrap-ui-sample/src/main/resources/js/jquery.validate.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout">
|
||||
<head>
|
||||
<title>Layout</title>
|
||||
<link rel="stylesheet"
|
||||
th:href="@{/resources/css/bootstrap.min.css}"
|
||||
href="../../resources/css/bootstrap.min.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="navbar">
|
||||
<div class="navbar-inner">
|
||||
<a class="brand"
|
||||
href="https://github.com/ultraq/thymeleaf-layout-dialect">
|
||||
Thymeleaf - Layout
|
||||
</a>
|
||||
<ul class="nav">
|
||||
<li>
|
||||
<a th:href="@{/}" href="messages.html">
|
||||
Messages
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<h1 layout:fragment="header">Layout</h1>
|
||||
<div layout:fragment="content">
|
||||
Fake content
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
|
||||
layout:decorator="layout">
|
||||
<head>
|
||||
<title>Messages : Create</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1 layout:fragment="header">Messages : Create</h1>
|
||||
<div layout:fragment="content"
|
||||
class="container">
|
||||
<form id="messageForm"
|
||||
th:action="@{/(form)}"
|
||||
th:object="${message}"
|
||||
action="#"
|
||||
method="post">
|
||||
<div th:if="${#fields.hasErrors('*')}"
|
||||
class="alert alert-error">
|
||||
<p th:each="error : ${#fields.errors('*')}"
|
||||
th:text="${error}">
|
||||
Validation error
|
||||
</p>
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
<a th:href="@{/}" href="messages.html">
|
||||
Messages
|
||||
</a>
|
||||
</div>
|
||||
<label for="summary">Summary</label>
|
||||
<input type="text"
|
||||
th:field="*{summary}"
|
||||
th:class="${#fields.hasErrors('summary')} ? 'field-error'"/>
|
||||
<label for="text">Message</label>
|
||||
<textarea
|
||||
th:field="*{text}"
|
||||
th:class="${#fields.hasErrors('text')} ? 'field-error'"></textarea>
|
||||
<div class="form-actions">
|
||||
<input type="submit" value="Create"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
|
||||
layout:decorator="layout">
|
||||
<head>
|
||||
<title>Messages : View all</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1 layout:fragment="header">Messages : View all</h1>
|
||||
<div layout:fragment="content" class="container">
|
||||
<div class="pull-right">
|
||||
<a href="form.html" th:href="@{/(form)}">Create Message</a>
|
||||
</div>
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>Created</td>
|
||||
<td>Summary</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:if="${messages.empty}">
|
||||
<td colspan="3">
|
||||
No messages
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:each="message : ${messages}">
|
||||
<td th:text="${message.id}">1</td>
|
||||
<td th:text="${#calendars.format(message.created)}">
|
||||
July 11, 2012 2:17:16 PM CDT
|
||||
</td>
|
||||
<td>
|
||||
<a href="view.html"
|
||||
th:href="@{'/' + ${message.id}}"
|
||||
th:text="${message.summary}">
|
||||
The summary
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<html xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
|
||||
layout:decorator="layout">
|
||||
<head>
|
||||
<title>Messages : View</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1 layout:fragment="header">Messages : Create</h1>
|
||||
<div layout:fragment="content"
|
||||
class="container">
|
||||
<div class="alert alert-success"
|
||||
th:if="${globalMessage}"
|
||||
th:text="${globalMessage}">
|
||||
Some Success message
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
<a th:href="@{/}" href="list.html">
|
||||
Messages
|
||||
</a>
|
||||
</div>
|
||||
<dl>
|
||||
<dt>ID</dt>
|
||||
<dd id="id" th:text="${message.id}">123</dd>
|
||||
<dt>Date</dt>
|
||||
<dd id="created"
|
||||
th:text="${#calendars.format(message.created)}">
|
||||
July 11, 2012 2:17:16 PM CDT
|
||||
</dd>
|
||||
<dt>Summary</dt>
|
||||
<dd id="summary"
|
||||
th:text="${message.summary}">
|
||||
A short summary...
|
||||
</dd>
|
||||
<dt>Message</dt>
|
||||
<dd id="text"
|
||||
th:text="${message.text}">
|
||||
A detailed message that is longer than the summary.
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
package org.springframework.bootstrap.sample.ui;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.bootstrap.SpringApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Basic integration tests for demo application.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class UiBootstrapApplicationTests {
|
||||
|
||||
private static ConfigurableApplicationContext context;
|
||||
|
||||
@BeforeClass
|
||||
public static void start() throws Exception {
|
||||
Future<ConfigurableApplicationContext> future = Executors
|
||||
.newSingleThreadExecutor().submit(
|
||||
new Callable<ConfigurableApplicationContext>() {
|
||||
@Override
|
||||
public ConfigurableApplicationContext call() throws Exception {
|
||||
return (ConfigurableApplicationContext) SpringApplication
|
||||
.run(UiBootstrapApplication.class);
|
||||
}
|
||||
});
|
||||
context = future.get(30, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stop() {
|
||||
if (context != null) {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHome() throws Exception {
|
||||
ResponseEntity<String> entity = getRestTemplate().getForEntity(
|
||||
"http://localhost:8080", String.class);
|
||||
assertEquals(HttpStatus.OK, entity.getStatusCode());
|
||||
assertTrue("Wrong body (title doesn't match):\n" + entity.getBody(), entity
|
||||
.getBody().contains("<title>Messages"));
|
||||
assertFalse("Wrong body (found layout:fragment):\n" + entity.getBody(), entity
|
||||
.getBody().contains("layout:fragment"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreate() throws Exception {
|
||||
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
|
||||
map.set("text", "FOO text");
|
||||
map.set("summary", "FOO");
|
||||
URI location = getRestTemplate().postForLocation("http://localhost:8080", map);
|
||||
assertTrue("Wrong location:\n" + location,
|
||||
location.toString().contains("localhost:8080"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCss() throws Exception {
|
||||
ResponseEntity<String> entity = getRestTemplate().getForEntity(
|
||||
"http://localhost:8080/css/bootstrap.min.css", String.class);
|
||||
assertEquals(HttpStatus.OK, entity.getStatusCode());
|
||||
assertTrue("Wrong body:\n" + entity.getBody(), entity.getBody().contains("body"));
|
||||
}
|
||||
|
||||
private RestTemplate getRestTemplate() {
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
|
||||
@Override
|
||||
public void handleError(ClientHttpResponse response) throws IOException {
|
||||
}
|
||||
});
|
||||
return restTemplate;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
handlers = java.util.logging.ConsoleHandler
|
||||
.level = INFO
|
||||
|
||||
java.util.logging.ConsoleHandler.level = FINE
|
||||
sun.net.www.protocol.http.HttpURLConnection.level = ALL
|
||||
org.springframework.bootstrap.context.annotation.level = ALL
|
||||
org.thymeleaf.level = ALL
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
|
|
@ -105,6 +106,16 @@
|
|||
<version>1.6</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf-spring3</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>nz.net.ultraq.web.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf-layout-dialect</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.bootstrap.autoconfigure;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.ResourceBundleMessageSource;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for {@link MessageSource}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(MessageSource.class)
|
||||
public class MessageSourceAutoConfiguration {
|
||||
|
||||
@Value("${spring.messages.basename:messages}")
|
||||
private String basename;
|
||||
|
||||
@Bean
|
||||
public MessageSource messageSource() {
|
||||
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
|
||||
messageSource.setBasename(this.basename);
|
||||
return messageSource;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -36,4 +36,5 @@ import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
|
|||
@ConditionalOnMissingBean(JpaRepositoryFactoryBean.class)
|
||||
@Import(JpaRepositoriesAutoConfigureRegistrar.class)
|
||||
public class JpaRepositoriesAutoConfiguration {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.springframework.bootstrap.autoconfigure.orm.jpa;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.ejb.HibernateEntityManager;
|
||||
import org.springframework.bootstrap.autoconfigure.jdbc.EmbeddedDatabaseAutoConfiguration;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
|
|
@ -36,7 +37,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|||
* @author Phillip Webb
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(name = "org.hibernate.ejb.HibernateEntityManager")
|
||||
@ConditionalOnClass(HibernateEntityManager.class)
|
||||
@EnableTransactionManagement
|
||||
public class HibernateJpaAutoConfiguration extends JpaAutoConfiguration {
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public abstract class JpaAutoConfiguration implements BeanFactoryAware {
|
|||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager txManager() {
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
return new JpaTransactionManager(entityManagerFactory().getObject());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.bootstrap.autoconfigure.thymeleaf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import nz.net.ultraq.web.thymeleaf.LayoutDialect;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnMissingBean;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnMissingClass;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.thymeleaf.TemplateProcessingParameters;
|
||||
import org.thymeleaf.resourceresolver.IResourceResolver;
|
||||
import org.thymeleaf.spring3.SpringTemplateEngine;
|
||||
import org.thymeleaf.spring3.view.ThymeleafViewResolver;
|
||||
import org.thymeleaf.templateresolver.ITemplateResolver;
|
||||
import org.thymeleaf.templateresolver.TemplateResolver;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Thymeleaf templating.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(SpringTemplateEngine.class)
|
||||
public class ThymeleafAutoConfiguration {
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(name = "defaultTemplateResolver")
|
||||
protected static class DefaultTemplateResolverConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||
|
||||
@Value("${spring.template.prefix:classpath:/templates/}")
|
||||
private String prefix = "classpath:/templates/";
|
||||
|
||||
@Value("${spring.template.suffix:.html}")
|
||||
private String suffix = ".html";
|
||||
|
||||
@Value("${spring.template.mode:HTML5}")
|
||||
private String templateMode = "HTML5";
|
||||
|
||||
@Bean
|
||||
public ITemplateResolver defaultTemplateResolver() {
|
||||
TemplateResolver resolver = new TemplateResolver();
|
||||
resolver.setResourceResolver(new IResourceResolver() {
|
||||
@Override
|
||||
public InputStream getResourceAsStream(
|
||||
TemplateProcessingParameters templateProcessingParameters,
|
||||
String resourceName) {
|
||||
try {
|
||||
return DefaultTemplateResolverConfiguration.this.resourceLoader
|
||||
.getResource(resourceName).getInputStream();
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "SPRING";
|
||||
}
|
||||
});
|
||||
resolver.setPrefix(this.prefix);
|
||||
resolver.setSuffix(this.suffix);
|
||||
resolver.setTemplateMode(this.templateMode);
|
||||
return resolver;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingClass("nz.net.ultraq.web.thymeleaf.LayoutDialect")
|
||||
@ConditionalOnMissingBean(SpringTemplateEngine.class)
|
||||
protected static class ThymeleafDefaultConfiguration {
|
||||
|
||||
@Autowired
|
||||
private Collection<ITemplateResolver> templateResolvers = Collections.emptySet();
|
||||
|
||||
@Bean
|
||||
public SpringTemplateEngine templateEngine() {
|
||||
SpringTemplateEngine engine = new SpringTemplateEngine();
|
||||
for (ITemplateResolver templateResolver : this.templateResolvers) {
|
||||
engine.addTemplateResolver(templateResolver);
|
||||
}
|
||||
return engine;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass({ LayoutDialect.class })
|
||||
@ConditionalOnMissingBean(SpringTemplateEngine.class)
|
||||
protected static class ThymeleafWebLayoutConfiguration {
|
||||
|
||||
@Autowired
|
||||
private Collection<ITemplateResolver> templateResolvers = Collections.emptySet();
|
||||
|
||||
@Bean
|
||||
public SpringTemplateEngine templateEngine() {
|
||||
SpringTemplateEngine engine = new SpringTemplateEngine();
|
||||
for (ITemplateResolver templateResolver : this.templateResolvers) {
|
||||
engine.addTemplateResolver(templateResolver);
|
||||
}
|
||||
engine.addDialect(new LayoutDialect());
|
||||
return engine;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass({ Servlet.class })
|
||||
protected static class ThymeleafViewResolverConfiguration {
|
||||
|
||||
@Autowired
|
||||
private SpringTemplateEngine templateEngine;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(name = "thymeleafViewResolver")
|
||||
public ThymeleafViewResolver thymeleafViewResolver() {
|
||||
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
|
||||
resolver.setTemplateEngine(this.templateEngine);
|
||||
return resolver;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -18,6 +18,8 @@ package org.springframework.bootstrap.autoconfigure.web;
|
|||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.bootstrap.autoconfigure.web.WebMvcAutoConfiguration.WebMvcConfiguration;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnMissingBean;
|
||||
|
|
@ -25,11 +27,16 @@ import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.format.Formatter;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
/**
|
||||
|
|
@ -51,6 +58,9 @@ public class WebMvcAutoConfiguration {
|
|||
@EnableWebMvc
|
||||
public static class WebMvcConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private ListableBeanFactory beanFactory;
|
||||
|
||||
@Bean
|
||||
public DispatcherServlet dispatcherServlet() {
|
||||
return new DispatcherServlet();
|
||||
|
|
@ -62,6 +72,29 @@ public class WebMvcAutoConfiguration {
|
|||
configurer.enable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFormatters(FormatterRegistry registry) {
|
||||
for (Converter<?, ?> converter : this.beanFactory.getBeansOfType(
|
||||
Converter.class).values()) {
|
||||
registry.addConverter(converter);
|
||||
}
|
||||
for (GenericConverter converter : this.beanFactory.getBeansOfType(
|
||||
GenericConverter.class).values()) {
|
||||
registry.addConverter(converter);
|
||||
}
|
||||
for (Formatter<?> formatter : this.beanFactory
|
||||
.getBeansOfType(Formatter.class).values()) {
|
||||
registry.addFormatter(formatter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/**").addResourceLocations("/")
|
||||
.addResourceLocations("classpath:/static")
|
||||
.addResourceLocations("classpath:/");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ import org.springframework.util.MultiValueMap;
|
|||
*/
|
||||
abstract class AbstractOnBeanCondition implements Condition {
|
||||
|
||||
private static Log logger = LogFactory.getLog(OnBeanCondition.class);
|
||||
protected Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected abstract Class<?> annotationClass();
|
||||
|
||||
|
|
@ -53,8 +53,8 @@ abstract class AbstractOnBeanCondition implements Condition {
|
|||
List<String> beanClassesFound = new ArrayList<String>();
|
||||
List<String> beanNamesFound = new ArrayList<String>();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Looking for beans with class: " + beanClasses);
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Looking for beans with class: " + beanClasses);
|
||||
}
|
||||
for (String beanClass : beanClasses) {
|
||||
try {
|
||||
|
|
@ -72,8 +72,8 @@ abstract class AbstractOnBeanCondition implements Condition {
|
|||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Looking for beans with names: " + beanNames);
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Looking for beans with names: " + beanNames);
|
||||
}
|
||||
for (String beanName : beanNames) {
|
||||
if (context.getBeanFactory().containsBeanDefinition(beanName)) {
|
||||
|
|
@ -82,8 +82,8 @@ abstract class AbstractOnBeanCondition implements Condition {
|
|||
}
|
||||
|
||||
boolean result = evaluate(beanClassesFound, beanNamesFound);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Finished matching and result is matches" + result);
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Finished matching and result is matches: " + result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.bootstrap.context.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
|
||||
/**
|
||||
* {@link Conditional} that only matches when the specified classes are on the classpath.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Conditional(OnMissingClassCondition.class)
|
||||
public @interface ConditionalOnMissingClass {
|
||||
|
||||
/**
|
||||
* The classes names that must be absent.
|
||||
* @return the class names that must be absent.
|
||||
*/
|
||||
public String[] value() default {};
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.bootstrap.context.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
|
||||
/**
|
||||
* {@link Conditional} that only matches when the application context is a not a web
|
||||
* application context.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Conditional(OnNotWebApplicationCondition.class)
|
||||
public @interface ConditionalOnNotWebApplication {
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.bootstrap.context.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
|
||||
/**
|
||||
* {@link Conditional} that only matches when the application context is a web application
|
||||
* context.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Conditional(OnWebApplicationCondition.class)
|
||||
public @interface ConditionalOnWebApplication {
|
||||
}
|
||||
|
|
@ -61,6 +61,9 @@ class OnClassCondition implements Condition {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Classes not found (search terminated with matches=true)");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.bootstrap.context.annotation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* {@link Condition} that checks for the specific classes.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see ConditionalOnMissingClass
|
||||
*/
|
||||
class OnMissingClassCondition implements Condition {
|
||||
|
||||
private static Log logger = LogFactory.getLog(OnMissingClassCondition.class);
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(
|
||||
ConditionalOnMissingClass.class.getName(), true);
|
||||
if (attributes != null) {
|
||||
List<String> classNames = new ArrayList<String>();
|
||||
collectClassNames(classNames, attributes.get("value"));
|
||||
Assert.isTrue(classNames.size() > 0,
|
||||
"@ConditionalOnMissingClass annotations must specify at least one class value");
|
||||
for (String className : classNames) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Checking for class: " + className);
|
||||
}
|
||||
if (ClassUtils.isPresent(className, context.getClassLoader())) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found class: " + className
|
||||
+ " (search terminated with matches=false)");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void collectClassNames(List<String> classNames, List<Object> values) {
|
||||
for (Object value : values) {
|
||||
for (Object valueItem : (Object[]) value) {
|
||||
classNames.add(valueItem instanceof Class<?> ? ((Class<?>) valueItem)
|
||||
.getName() : valueItem.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.bootstrap.context.annotation;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link Condition} that checks for a web application context and returns false if one is
|
||||
* found.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see ConditionalOnNotWebApplication
|
||||
*/
|
||||
class OnNotWebApplicationCondition implements Condition {
|
||||
|
||||
private static Log logger = LogFactory.getLog(OnNotWebApplicationCondition.class);
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
if (!ClassUtils.isPresent(
|
||||
"org.springframework.web.context.support.GenericWebApplicationContext",
|
||||
null)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Web application classes not found");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
boolean result = !StringUtils.arrayToCommaDelimitedString(
|
||||
context.getBeanFactory().getRegisteredScopeNames()).contains("session");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Web application context found: " + !result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.bootstrap.context.annotation;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.support.StandardServletEnvironment;
|
||||
|
||||
/**
|
||||
* {@link Condition} that checks for a web application context.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see ConditionalOnWebApplication
|
||||
*/
|
||||
class OnWebApplicationCondition implements Condition {
|
||||
|
||||
private static Log logger = LogFactory.getLog(OnWebApplicationCondition.class);
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
if (!ClassUtils.isPresent(
|
||||
"org.springframework.web.context.support.GenericWebApplicationContext",
|
||||
null)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Web application classes not found");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
boolean result = StringUtils.arrayToCommaDelimitedString(
|
||||
context.getBeanFactory().getRegisteredScopeNames()).contains("session")
|
||||
|| context.getEnvironment() instanceof StandardServletEnvironment;
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Web application context found: " + result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -320,7 +320,7 @@ public abstract class AbstractEmbeddedServletContainerFactory implements
|
|||
*/
|
||||
protected final File getValidDocumentRoot() {
|
||||
File[] roots = new File[] { getDocumentRoot(), new File("src/main/webapp"),
|
||||
new File("public") };
|
||||
new File("public"), new File("static") };
|
||||
for (File root : roots) {
|
||||
if (root != null && root.exists() && root.isDirectory()) {
|
||||
return root.getAbsoluteFile();
|
||||
|
|
|
|||
|
|
@ -14,12 +14,14 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.bootstrap.logging;
|
||||
package org.springframework.bootstrap.context.initializer;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.bootstrap.logging.JavaLoggerConfigurer;
|
||||
import org.springframework.bootstrap.logging.LogbackConfigurer;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
|
@ -198,7 +200,7 @@ public class LoggingInitializer implements
|
|||
}
|
||||
|
||||
// Fallback to the default
|
||||
String defaultPath = ClassUtils.getPackageName(LoggingInitializer.class);
|
||||
String defaultPath = ClassUtils.getPackageName(JavaLoggerConfigurer.class);
|
||||
defaultPath = defaultPath.replace(".", "/");
|
||||
defaultPath = defaultPath + "/" + this.paths[this.paths.length - 1];
|
||||
return "classpath:" + defaultPath;
|
||||
|
|
@ -1,13 +1,16 @@
|
|||
org.springframework.bootstrap.context.annotation.EnableAutoConfiguration=\
|
||||
org.springframework.bootstrap.autoconfigure.PropertyPlaceholderAutoConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.MessageSourceAutoConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.data.JpaRepositoriesAutoConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.jdbc.EmbeddedDatabaseAutoConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.batch.BatchAutoConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.web.EmbeddedContainerCustomizerConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.web.EmbeddedJettyAutoConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.web.EmbeddedTomcatAutoConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.web.WebMvcAutoConfiguration
|
||||
org.springframework.context.ApplicationContextInitializer=\
|
||||
org.springframework.bootstrap.context.initializer.ConfigFileApplicationContextInitializer,\
|
||||
org.springframework.bootstrap.context.initializer.LoggingInitializer,\
|
||||
org.springframework.bootstrap.context.initializer.EnvironmentDelegateApplicationContextInitializer
|
||||
|
|
@ -290,7 +290,7 @@ public class SpringApplicationTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void exitWithExplicitCOde() throws Exception {
|
||||
public void exitWithExplicitCode() throws Exception {
|
||||
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||
application.setWebEnvironment(false);
|
||||
ApplicationContext context = application.run();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.bootstrap.autoconfigure;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class MessageSourceAutoConfigurationTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@Test
|
||||
public void testDefaultMessageSource() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
this.context.register(MessageSourceAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertEquals("Foo message",
|
||||
this.context.getMessage("foo", null, "Foo message", Locale.UK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageSourceCreated() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
this.context.register(MessageSourceAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("spring.messages.basename", "test/messages");
|
||||
this.context.getEnvironment().getPropertySources()
|
||||
.addFirst(new MapPropertySource("test", map));
|
||||
this.context.refresh();
|
||||
assertEquals("bar",
|
||||
this.context.getMessage("foo", null, "Foo message", Locale.UK));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.bootstrap.autoconfigure.thymeleaf;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.bootstrap.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.servlet.support.RequestContext;
|
||||
import org.thymeleaf.TemplateEngine;
|
||||
import org.thymeleaf.context.Context;
|
||||
import org.thymeleaf.spring3.view.ThymeleafView;
|
||||
import org.thymeleaf.spring3.view.ThymeleafViewResolver;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class ThymeleafAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void createFromConfigClass() throws Exception {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.register(ThymeleafAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("spring.template.mode", "XHTML");
|
||||
map.put("spring.template.suffix", "");
|
||||
context.getEnvironment().getPropertySources()
|
||||
.addFirst(new MapPropertySource("test", map));
|
||||
context.refresh();
|
||||
TemplateEngine engine = context.getBean(TemplateEngine.class);
|
||||
Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar"));
|
||||
String result = engine.process("template.txt", attrs);
|
||||
assertEquals("<html>bar</html>", result);
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createLayoutFromConfigClass() throws Exception {
|
||||
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
||||
context.register(ThymeleafAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
MockServletContext servletContext = new MockServletContext();
|
||||
context.setServletContext(servletContext);
|
||||
context.refresh();
|
||||
ThymeleafView view = (ThymeleafView) context.getBean(ThymeleafViewResolver.class)
|
||||
.resolveViewName("view", Locale.UK);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAttribute(RequestContext.WEB_APPLICATION_CONTEXT_ATTRIBUTE, context);
|
||||
view.render(Collections.singletonMap("foo", "bar"), request, response);
|
||||
String result = response.getContentAsString();
|
||||
assertTrue("Wrong result: " + result, result.contains("<title>Content</title>"));
|
||||
assertTrue("Wrong result: " + result, result.contains("<span>bar</span>"));
|
||||
context.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ import org.apache.commons.logging.LogFactory;
|
|||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.bootstrap.context.initializer.LoggingInitializer;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
<pattern>${LOG_PATTERN}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<logger name="org.springframework.beans.factory.annotation" level="TRACE" />
|
||||
<logger name="org.springframework.bootstrap.context.annotation" level="TRACE" />
|
||||
<logger name="org.thymeleaf" level="TRACE" />
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
</root>
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
body: {background: red}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout">
|
||||
<head>
|
||||
<title layout:fragment="title">Layout</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 layout:fragment="title">Layout</h1>
|
||||
<div layout:fragment="content">
|
||||
Fake content
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1 @@
|
|||
<html th:text="${foo}">foo</html>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<!DOCTYPE tiles-definitions PUBLIC
|
||||
"-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
|
||||
"http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
|
||||
<tiles-definitions>
|
||||
<definition name="*" template="layout">
|
||||
<put-attribute name="content" value="content/{1}" />
|
||||
<put-attribute name="title" value="title/{1}" />
|
||||
</definition>
|
||||
|
||||
<definition name="content/*" template="{1} :: content" />
|
||||
<definition name="title/*" template="{1} :: title" />
|
||||
</tiles-definitions>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout" layout:decorator="layout">
|
||||
<head>
|
||||
<title layout:fragment="title">Content</title>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
<span th:text="${foo}">foo</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1 @@
|
|||
foo=bar
|
||||
Loading…
Reference in New Issue