Add sample project for Groovy templates
This commit is contained in:
		
							parent
							
								
									334c8142c4
								
							
						
					
					
						commit
						523956e2fe
					
				| 
						 | 
				
			
			@ -44,6 +44,7 @@
 | 
			
		|||
		<module>spring-boot-sample-tomcat-multi-connectors</module>
 | 
			
		||||
		<module>spring-boot-sample-traditional</module>
 | 
			
		||||
		<module>spring-boot-sample-web-freemarker</module>
 | 
			
		||||
		<module>spring-boot-sample-web-groovy-template</module>
 | 
			
		||||
		<module>spring-boot-sample-web-method-security</module>
 | 
			
		||||
		<module>spring-boot-sample-web-secure</module>
 | 
			
		||||
		<module>spring-boot-sample-web-static</module>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
This sample application uses Spring Boot and
 | 
			
		||||
[Groovy templates](http://beta.groovy-lang.org/docs/groovy-2.3.0/html/documentation/markup-template-engine.html)
 | 
			
		||||
in the View layer. The templates for this app live in
 | 
			
		||||
`classpath:/templates/`, which is the conventional location for Spring
 | 
			
		||||
Boot. External configuration is available via
 | 
			
		||||
"spring.groovy.template.*".
 | 
			
		||||
 | 
			
		||||
The templates all use a fixed "layout" implemented anticipating
 | 
			
		||||
changes in Groovy 2.3.1 using a custom `BaseTemplate` class
 | 
			
		||||
(`LayoutAwareTemplate`).
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
<?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>
 | 
			
		||||
		<!-- Your own application should inherit from spring-boot-starter-parent -->
 | 
			
		||||
		<groupId>org.springframework.boot</groupId>
 | 
			
		||||
		<artifactId>spring-boot-samples</artifactId>
 | 
			
		||||
		<version>1.1.0.BUILD-SNAPSHOT</version>
 | 
			
		||||
	</parent>
 | 
			
		||||
	<artifactId>spring-boot-sample-web-groovy-templates</artifactId>
 | 
			
		||||
	<name>spring-boot-sample-web-groovy-templates</name>
 | 
			
		||||
	<description>Spring Boot Web UI Sample</description>
 | 
			
		||||
	<url>http://projects.spring.io/spring-boot/</url>
 | 
			
		||||
	<organization>
 | 
			
		||||
		<name>Pivotal Software, Inc.</name>
 | 
			
		||||
		<url>http://www.spring.io</url>
 | 
			
		||||
	</organization>
 | 
			
		||||
	<properties>
 | 
			
		||||
		<main.basedir>${basedir}/../..</main.basedir>
 | 
			
		||||
	</properties>
 | 
			
		||||
	<dependencies>
 | 
			
		||||
		<dependency>
 | 
			
		||||
			<groupId>org.springframework.boot</groupId>
 | 
			
		||||
			<artifactId>spring-boot-starter-web</artifactId>
 | 
			
		||||
		</dependency>
 | 
			
		||||
		<dependency>
 | 
			
		||||
			<groupId>org.codehaus.groovy</groupId>
 | 
			
		||||
			<artifactId>groovy-templates</artifactId>
 | 
			
		||||
		</dependency>
 | 
			
		||||
		<dependency>
 | 
			
		||||
			<groupId>org.springframework.boot</groupId>
 | 
			
		||||
			<artifactId>spring-boot-starter-test</artifactId>
 | 
			
		||||
			<scope>test</scope>
 | 
			
		||||
		</dependency>
 | 
			
		||||
	</dependencies>
 | 
			
		||||
	<build>
 | 
			
		||||
		<plugins>
 | 
			
		||||
			<plugin>
 | 
			
		||||
				<groupId>org.springframework.boot</groupId>
 | 
			
		||||
				<artifactId>spring-boot-maven-plugin</artifactId>
 | 
			
		||||
				<dependencies>
 | 
			
		||||
					<dependency>
 | 
			
		||||
						<groupId>org.springframework</groupId>
 | 
			
		||||
						<artifactId>springloaded</artifactId>
 | 
			
		||||
						<version>1.2.0.RELEASE</version>
 | 
			
		||||
					</dependency>
 | 
			
		||||
				</dependencies>
 | 
			
		||||
			</plugin>
 | 
			
		||||
		</plugins>
 | 
			
		||||
	</build>
 | 
			
		||||
</project>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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 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 final 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,66 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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 sample.ui;
 | 
			
		||||
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
 | 
			
		||||
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 Date created = new Date();
 | 
			
		||||
 | 
			
		||||
	public Long getId() {
 | 
			
		||||
		return this.id;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setId(Long id) {
 | 
			
		||||
		this.id = id;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Date getCreated() {
 | 
			
		||||
		return this.created;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setCreated(Date 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,27 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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 sample.ui;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author Rob Winch
 | 
			
		||||
 */
 | 
			
		||||
public interface MessageRepository {
 | 
			
		||||
 | 
			
		||||
	Iterable<Message> findAll();
 | 
			
		||||
 | 
			
		||||
	Message save(Message message);
 | 
			
		||||
 | 
			
		||||
	Message findMessage(Long id);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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 sample.ui;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.SpringApplication;
 | 
			
		||||
import org.springframework.boot.autoconfigure.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 SampleGroovyTemplateApplication {
 | 
			
		||||
 | 
			
		||||
	@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(SampleGroovyTemplateApplication.class, args);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,92 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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 sample.ui.mvc;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import javax.validation.Valid;
 | 
			
		||||
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.stereotype.Controller;
 | 
			
		||||
import org.springframework.validation.BindingResult;
 | 
			
		||||
import org.springframework.validation.FieldError;
 | 
			
		||||
import org.springframework.validation.ObjectError;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
import sample.ui.Message;
 | 
			
		||||
import sample.ui.MessageRepository;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author Rob Winch
 | 
			
		||||
 */
 | 
			
		||||
@Controller
 | 
			
		||||
@RequestMapping("/")
 | 
			
		||||
public class MessageController {
 | 
			
		||||
	private final MessageRepository messageRepository;
 | 
			
		||||
 | 
			
		||||
	@Autowired
 | 
			
		||||
	public MessageController(MessageRepository messageRepository) {
 | 
			
		||||
		this.messageRepository = messageRepository;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@RequestMapping
 | 
			
		||||
	public ModelAndView list() {
 | 
			
		||||
		Iterable<Message> messages = this.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()) {
 | 
			
		||||
			ModelAndView mav = new ModelAndView("messages/form");
 | 
			
		||||
			mav.addObject("formErrors", result.getAllErrors());
 | 
			
		||||
			mav.addObject("fieldErrors", getFieldErrors(result));
 | 
			
		||||
			return mav;
 | 
			
		||||
		}
 | 
			
		||||
		message = this.messageRepository.save(message);
 | 
			
		||||
		redirect.addFlashAttribute("globalMessage", "Successfully created a new message");
 | 
			
		||||
		return new ModelAndView("redirect:/{message.id}", "message.id", message.getId());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private Map<String, ObjectError> getFieldErrors(BindingResult result) {
 | 
			
		||||
		Map<String, ObjectError> map = new HashMap<String, ObjectError>();
 | 
			
		||||
		for (FieldError error : result.getFieldErrors()) {
 | 
			
		||||
			map.put(error.getField(), error);
 | 
			
		||||
		}
 | 
			
		||||
		return map ;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@RequestMapping("foo")
 | 
			
		||||
	public String foo() {
 | 
			
		||||
		throw new RuntimeException("Expected exception in controller");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
# Allow templates to be reloaded at dev time
 | 
			
		||||
spring.groovy.template.cache: false
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<configuration>
 | 
			
		||||
 | 
			
		||||
	<include resource="org/springframework/boot/logging/logback/base.xml"/>
 | 
			
		||||
 | 
			
		||||
	<logger name="org.springframework.web" level="DEBUG"/>
 | 
			
		||||
 | 
			
		||||
</configuration>
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										9404
									
								
								spring-boot-samples/spring-boot-sample-web-groovy-templates/src/main/resources/static/js/jquery-1.7.2.js
								
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										9404
									
								
								spring-boot-samples/spring-boot-sample-web-groovy-templates/src/main/resources/static/js/jquery-1.7.2.js
								
								
								
									vendored
								
								
									Normal file
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
html {
 | 
			
		||||
  head {
 | 
			
		||||
    title(title)
 | 
			
		||||
    link(rel:'stylesheet', href:'/css/bootstrap.min.css')
 | 
			
		||||
  }
 | 
			
		||||
  body {
 | 
			
		||||
    div(class:'container') {
 | 
			
		||||
      div(class:'navbar') {
 | 
			
		||||
        div(class:'navbar-inner') {
 | 
			
		||||
          a(class:'brand',
 | 
			
		||||
              href:'http://beta.groovy-lang.org/docs/groovy-2.3.0/html/documentation/markup-template-engine.html') {
 | 
			
		||||
              yield 'Groovy - Layout'
 | 
			
		||||
          }
 | 
			
		||||
          ul(class:'nav') {
 | 
			
		||||
            li {
 | 
			
		||||
              a(href:'/') {
 | 
			
		||||
                yield 'Messages'
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      h1(title)
 | 
			
		||||
      div { content() }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
layout 'layout.tpl', title: 'Messages : Create',
 | 
			
		||||
  content: contents {
 | 
			
		||||
    div (class:'container') {
 | 
			
		||||
      form (id:'messageForm', action:'/', method:'post') {
 | 
			
		||||
      	if (formErrors) {
 | 
			
		||||
          div(class:'alert alert-error') {
 | 
			
		||||
            formErrors.each { error ->
 | 
			
		||||
              p error.defaultMessage
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        div (class:'pull-right') {
 | 
			
		||||
          a (href:'/', 'Messages')
 | 
			
		||||
        }
 | 
			
		||||
        label (for:'summary', 'Summary')
 | 
			
		||||
        input (name:'summary', type:'text', value:message.summary?:'',
 | 
			
		||||
            class:fieldErrors?.summary ? 'field-error' : 'none')
 | 
			
		||||
        label (for:'text', 'Message')
 | 
			
		||||
        textarea (name:'text', class:fieldErrors?.text ? 'field-error' : 'none', message.text?:'')
 | 
			
		||||
        div (class:'form-actions') {
 | 
			
		||||
          input (type:'submit', value:'Create')
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
layout 'layout.tpl', title: 'Messages : View all',
 | 
			
		||||
  content: contents {
 | 
			
		||||
    div(class:'container') {
 | 
			
		||||
      div(class:'pull-right') {
 | 
			
		||||
        a(href:'/?form', 'Create Message')
 | 
			
		||||
      }
 | 
			
		||||
      table(class:'table table-bordered table-striped') {
 | 
			
		||||
        thead {
 | 
			
		||||
          tr {
 | 
			
		||||
            td 'ID'
 | 
			
		||||
            td 'Created'
 | 
			
		||||
            td 'Summary'
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        tbody {
 | 
			
		||||
          if (messages.empty) { tr { td(colspan:'3', 'No Messages' ) } }
 | 
			
		||||
          messages.each { message ->
 | 
			
		||||
            tr { 
 | 
			
		||||
              td message.id
 | 
			
		||||
              td "${message.created}"
 | 
			
		||||
              td {
 | 
			
		||||
                a(href:"/${message.id}") {
 | 
			
		||||
                  yield message.getSummary()
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
layout 'layout.tpl', title:'Messages : View',
 | 
			
		||||
  content: contents {
 | 
			
		||||
    div(class:'container') {
 | 
			
		||||
      if (globalMessage) {
 | 
			
		||||
        div (class:'alert alert-success', globalMessage)
 | 
			
		||||
      }
 | 
			
		||||
      div(class:'pull-right') {
 | 
			
		||||
        a(href:'/', 'Messages')
 | 
			
		||||
      }
 | 
			
		||||
      dl {
 | 
			
		||||
        dt 'ID'
 | 
			
		||||
        dd(id:'id', message.id)
 | 
			
		||||
        dt 'Date'
 | 
			
		||||
        dd(id:'created', "${message.created}")
 | 
			
		||||
        dt 'Summary'
 | 
			
		||||
        dd(id:'summary', message.summary)
 | 
			
		||||
        dt 'Message'
 | 
			
		||||
        dd(id:'text', message.text)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,111 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright 2012-2014 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 sample.ui;
 | 
			
		||||
 | 
			
		||||
import static org.hamcrest.Matchers.containsString;
 | 
			
		||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
 | 
			
		||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
 | 
			
		||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
 | 
			
		||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
 | 
			
		||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 | 
			
		||||
 | 
			
		||||
import java.util.regex.Pattern;
 | 
			
		||||
 | 
			
		||||
import org.hamcrest.Description;
 | 
			
		||||
import org.hamcrest.TypeSafeMatcher;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.boot.test.SpringApplicationConfiguration;
 | 
			
		||||
import org.springframework.test.annotation.DirtiesContext;
 | 
			
		||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 | 
			
		||||
import org.springframework.test.context.web.WebAppConfiguration;
 | 
			
		||||
import org.springframework.test.web.servlet.MockMvc;
 | 
			
		||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 | 
			
		||||
import org.springframework.web.context.WebApplicationContext;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A Basic Spring MVC Test for the Sample Controller"
 | 
			
		||||
 * 
 | 
			
		||||
 * @author Biju Kunjummen
 | 
			
		||||
 * @author Doo-Hwan, Kwak
 | 
			
		||||
 */
 | 
			
		||||
@RunWith(SpringJUnit4ClassRunner.class)
 | 
			
		||||
@WebAppConfiguration
 | 
			
		||||
@SpringApplicationConfiguration(classes = SampleGroovyTemplateApplication.class)
 | 
			
		||||
@DirtiesContext
 | 
			
		||||
public class MessageControllerWebTests {
 | 
			
		||||
 | 
			
		||||
	@Autowired
 | 
			
		||||
	private WebApplicationContext wac;
 | 
			
		||||
 | 
			
		||||
	private MockMvc mockMvc;
 | 
			
		||||
 | 
			
		||||
	@Before
 | 
			
		||||
	public void setup() {
 | 
			
		||||
		this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void testHome() throws Exception {
 | 
			
		||||
		this.mockMvc.perform(get("/")).andExpect(status().isOk())
 | 
			
		||||
				.andExpect(content().string(containsString("<title>Messages")));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void testCreate() throws Exception {
 | 
			
		||||
		this.mockMvc.perform(post("/").param("text", "FOO text").param("summary", "FOO"))
 | 
			
		||||
				.andExpect(status().isMovedTemporarily())
 | 
			
		||||
				.andExpect(header().string("location", RegexMatcher.matches("/[0-9]+")));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void testCreateValidation() throws Exception {
 | 
			
		||||
		this.mockMvc.perform(post("/").param("text", "").param("summary", ""))
 | 
			
		||||
				.andExpect(status().isOk())
 | 
			
		||||
				.andExpect(content().string(containsString("is required")));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static class RegexMatcher extends TypeSafeMatcher<String> {
 | 
			
		||||
		private final String regex;
 | 
			
		||||
 | 
			
		||||
		public RegexMatcher(String regex) {
 | 
			
		||||
			this.regex = regex;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static org.hamcrest.Matcher<java.lang.String> matches(String regex) {
 | 
			
		||||
			return new RegexMatcher(regex);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public boolean matchesSafely(String item) {
 | 
			
		||||
			return Pattern.compile(this.regex).matcher(item).find();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public void describeMismatchSafely(String item, Description mismatchDescription) {
 | 
			
		||||
			mismatchDescription.appendText("was \"").appendText(item).appendText("\"");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public void describeTo(Description description) {
 | 
			
		||||
			description.appendText("a string that matches regex: ")
 | 
			
		||||
					.appendText(this.regex);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,84 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright 2012-2014 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 sample.ui;
 | 
			
		||||
 | 
			
		||||
import static org.junit.Assert.assertEquals;
 | 
			
		||||
import static org.junit.Assert.assertFalse;
 | 
			
		||||
import static org.junit.Assert.assertTrue;
 | 
			
		||||
 | 
			
		||||
import java.net.URI;
 | 
			
		||||
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Value;
 | 
			
		||||
import org.springframework.boot.test.IntegrationTest;
 | 
			
		||||
import org.springframework.boot.test.SpringApplicationConfiguration;
 | 
			
		||||
import org.springframework.boot.test.TestRestTemplate;
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.test.annotation.DirtiesContext;
 | 
			
		||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 | 
			
		||||
import org.springframework.test.context.web.WebAppConfiguration;
 | 
			
		||||
import org.springframework.util.LinkedMultiValueMap;
 | 
			
		||||
import org.springframework.util.MultiValueMap;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Basic integration tests for demo application.
 | 
			
		||||
 * 
 | 
			
		||||
 * @author Dave Syer
 | 
			
		||||
 */
 | 
			
		||||
@RunWith(SpringJUnit4ClassRunner.class)
 | 
			
		||||
@SpringApplicationConfiguration(classes = SampleGroovyTemplateApplication.class)
 | 
			
		||||
@WebAppConfiguration
 | 
			
		||||
@IntegrationTest("server.port:0")
 | 
			
		||||
@DirtiesContext
 | 
			
		||||
public class SampleGroovyTemplateApplicationTests {
 | 
			
		||||
 | 
			
		||||
	@Value("${local.server.port}")
 | 
			
		||||
	private int port;
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void testHome() throws Exception {
 | 
			
		||||
		ResponseEntity<String> entity = new TestRestTemplate().getForEntity(
 | 
			
		||||
				"http://localhost:" + this.port, 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 = new TestRestTemplate().postForLocation("http://localhost:"
 | 
			
		||||
				+ this.port, map);
 | 
			
		||||
		assertTrue("Wrong location:\n" + location,
 | 
			
		||||
				location.toString().contains("localhost:" + this.port));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void testCss() throws Exception {
 | 
			
		||||
		ResponseEntity<String> entity = new TestRestTemplate().getForEntity(
 | 
			
		||||
				"http://localhost:" + this.port + "/css/bootstrap.min.css", String.class);
 | 
			
		||||
		assertEquals(HttpStatus.OK, entity.getStatusCode());
 | 
			
		||||
		assertTrue("Wrong body:\n" + entity.getBody(), entity.getBody().contains("body"));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue