pull/1652/merge
Phillip Webb 10 years ago
parent 09d5812c3b
commit 62eb01f0b8

@ -73,7 +73,7 @@ import com.codahale.metrics.MetricRegistry;
* In addition if Codahale's metrics library is on the classpath a {@link MetricRegistry} * In addition if Codahale's metrics library is on the classpath a {@link MetricRegistry}
* will be created and wired up to the counter and gauge services in addition to the basic * will be created and wired up to the counter and gauge services in addition to the basic
* repository. Users can create Codahale metrics by prefixing their metric names with the * repository. Users can create Codahale metrics by prefixing their metric names with the
* appropriate type (e.g. "histogram.*", "meter.*") and sending them to the standard * appropriate type (e.g. "histogram.*", "meter.*") and sending them to the standard
* <code>GaugeService</code> or <code>CounterService</code>. * <code>GaugeService</code> or <code>CounterService</code>.
* </p> * </p>
* <p> * <p>

@ -49,18 +49,14 @@ public class RichGaugeReaderPublicMetrics implements PublicMetrics {
return result; return result;
} }
private List<Metric<?>> convert(RichGauge richGauge) { private List<Metric<?>> convert(RichGauge gauge) {
List<Metric<?>> result = new ArrayList<Metric<?>>(6); List<Metric<?>> result = new ArrayList<Metric<?>>(6);
result.add(new Metric<Double>(gauge.getName() + RichGauge.AVG, gauge.getAverage()));
result.add(new Metric<Double>(richGauge.getName() + RichGauge.AVG, richGauge result.add(new Metric<Double>(gauge.getName() + RichGauge.VAL, gauge.getValue()));
.getAverage())); result.add(new Metric<Double>(gauge.getName() + RichGauge.MIN, gauge.getMin()));
result.add(new Metric<Double>(richGauge.getName() + RichGauge.VAL, richGauge.getValue())); result.add(new Metric<Double>(gauge.getName() + RichGauge.MAX, gauge.getMax()));
result.add(new Metric<Double>(richGauge.getName() + RichGauge.MIN, richGauge.getMin())); result.add(new Metric<Double>(gauge.getName() + RichGauge.ALPHA, gauge.getAlpha()));
result.add(new Metric<Double>(richGauge.getName() + RichGauge.MAX, richGauge.getMax())); result.add(new Metric<Long>(gauge.getName() + RichGauge.COUNT, gauge.getCount()));
result.add(new Metric<Double>(richGauge.getName() + RichGauge.ALPHA, richGauge
.getAlpha()));
result.add(new Metric<Long>(richGauge.getName() + RichGauge.COUNT, richGauge.getCount()));
return result; return result;
} }

@ -32,10 +32,15 @@ import org.springframework.util.Assert;
public final class RichGauge { public final class RichGauge {
public static final String COUNT = ".count"; public static final String COUNT = ".count";
public static final String MAX = ".max"; public static final String MAX = ".max";
public static final String MIN = ".min"; public static final String MIN = ".min";
public static final String AVG = ".avg"; public static final String AVG = ".avg";
public static final String ALPHA = ".alpha"; public static final String ALPHA = ".alpha";
public static final String VAL = ".val"; public static final String VAL = ".val";
private final String name; private final String name;

@ -37,6 +37,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
@ -56,8 +57,8 @@ import com.fasterxml.jackson.databind.SerializationFeature;
* *
* @author Oliver Gierke * @author Oliver Gierke
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Sebastien Deleuze
* @author Marcel Overdijk * @author Marcel Overdijk
* @author Sebastien Deleuze
* @since 1.1.0 * @since 1.1.0
*/ */
@Configuration @Configuration
@ -99,29 +100,25 @@ public class JacksonAutoConfiguration {
static class JacksonObjectMapperBuilderAutoConfiguration { static class JacksonObjectMapperBuilderAutoConfiguration {
@Autowired @Autowired
private HttpMapperProperties httpMapperProperties = new HttpMapperProperties(); private JacksonProperties jacksonProperties;
@Autowired @Autowired
private JacksonProperties jacksonProperties = new JacksonProperties(); private HttpMapperProperties httpMapperProperties;
@Bean @Bean
@ConditionalOnMissingBean(Jackson2ObjectMapperBuilder.class) @ConditionalOnMissingBean(Jackson2ObjectMapperBuilder.class)
public Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder() { public Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
if (this.httpMapperProperties.isJsonSortKeys()) { if (this.httpMapperProperties.isJsonSortKeys()) {
builder.featuresToEnable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS); builder.featuresToEnable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
} }
configureFeatures(builder, this.jacksonProperties.getDeserialization()); configureFeatures(builder, this.jacksonProperties.getDeserialization());
configureFeatures(builder, this.jacksonProperties.getSerialization()); configureFeatures(builder, this.jacksonProperties.getSerialization());
configureFeatures(builder, this.jacksonProperties.getMapper()); configureFeatures(builder, this.jacksonProperties.getMapper());
configureFeatures(builder, this.jacksonProperties.getParser()); configureFeatures(builder, this.jacksonProperties.getParser());
configureFeatures(builder, this.jacksonProperties.getGenerator()); configureFeatures(builder, this.jacksonProperties.getGenerator());
configureDateFormat(builder); configureDateFormat(builder);
configurePropertyNamingStrategy(builder); configurePropertyNamingStrategy(builder);
return builder; return builder;
} }
@ -137,53 +134,57 @@ public class JacksonAutoConfiguration {
} }
} }
private void configureDateFormat(Jackson2ObjectMapperBuilder builder) {
// We support a fully qualified class name extending DateFormat or a date
// pattern string value
String dateFormat = this.jacksonProperties.getDateFormat();
if (dateFormat != null) {
try {
Class<?> dateFormatClass = ClassUtils.forName(dateFormat, null);
builder.dateFormat((DateFormat) BeanUtils
.instantiateClass(dateFormatClass));
}
catch (ClassNotFoundException ex) {
builder.dateFormat(new SimpleDateFormat(dateFormat));
}
}
}
private void configurePropertyNamingStrategy(Jackson2ObjectMapperBuilder builder) { private void configurePropertyNamingStrategy(Jackson2ObjectMapperBuilder builder) {
// We support a fully qualified class name extending Jackson's // We support a fully qualified class name extending Jackson's
// PropertyNamingStrategy or a string value corresponding to the constant // PropertyNamingStrategy or a string value corresponding to the constant
// names in PropertyNamingStrategy which hold default provided implementations // names in PropertyNamingStrategy which hold default provided implementations
String propertyNamingStrategy = this.jacksonProperties String strategy = this.jacksonProperties.getPropertyNamingStrategy();
.getPropertyNamingStrategy(); if (strategy != null) {
if (propertyNamingStrategy != null) {
try { try {
Class<?> clazz = ClassUtils.forName(propertyNamingStrategy, null); configurePropertyNamingStrategyClass(builder,
builder.propertyNamingStrategy((PropertyNamingStrategy) BeanUtils ClassUtils.forName(strategy, null));
.instantiateClass(clazz));
} }
catch (ClassNotFoundException e) { catch (ClassNotFoundException ex) {
// Find the field (this way we automatically support new constants configurePropertyNamingStrategyField(builder, strategy);
// that may be added by Jackson in the future)
Field field = ReflectionUtils.findField(PropertyNamingStrategy.class,
propertyNamingStrategy, PropertyNamingStrategy.class);
if (field != null) {
try {
builder.propertyNamingStrategy((PropertyNamingStrategy) field
.get(null));
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
else {
throw new IllegalArgumentException("Constant named '"
+ propertyNamingStrategy + "' not found on "
+ PropertyNamingStrategy.class.getName());
}
} }
} }
} }
private void configureDateFormat(Jackson2ObjectMapperBuilder builder) { private void configurePropertyNamingStrategyClass(
// We support a fully qualified class name extending DateFormat or a date Jackson2ObjectMapperBuilder builder, Class<?> propertyNamingStrategyClass) {
// pattern string value builder.propertyNamingStrategy((PropertyNamingStrategy) BeanUtils
String dateFormat = this.jacksonProperties.getDateFormat(); .instantiateClass(propertyNamingStrategyClass));
if (dateFormat != null) { }
try {
Class<?> clazz = ClassUtils.forName(dateFormat, null); private void configurePropertyNamingStrategyField(
builder.dateFormat((DateFormat) BeanUtils.instantiateClass(clazz)); Jackson2ObjectMapperBuilder builder, String fieldName) {
} // Find the field (this way we automatically support new constants
catch (ClassNotFoundException e) { // that may be added by Jackson in the future)
builder.dateFormat(new SimpleDateFormat(dateFormat)); Field field = ReflectionUtils.findField(PropertyNamingStrategy.class,
} fieldName, PropertyNamingStrategy.class);
Assert.notNull(field, "Constant named '" + fieldName + "' not found on "
+ PropertyNamingStrategy.class.getName());
try {
builder.propertyNamingStrategy((PropertyNamingStrategy) field.get(null));
}
catch (Exception ex) {
throw new IllegalStateException(ex);
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,6 +29,7 @@ import org.glassfish.jersey.servlet.ServletProperties;
import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -44,8 +45,9 @@ import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.filter.RequestContextFilter; import org.springframework.web.filter.RequestContextFilter;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for Jersey.
*
* @author Dave Syer * @author Dave Syer
*
*/ */
@Configuration @Configuration
@ConditionalOnClass({ SpringComponentProvider.class, ServletRegistration.class }) @ConditionalOnClass({ SpringComponentProvider.class, ServletRegistration.class })
@ -65,7 +67,7 @@ public class JerseyAutoConfiguration implements WebApplicationInitializer {
@PostConstruct @PostConstruct
public void path() { public void path() {
path = findPath(AnnotationUtils.findAnnotation(config.getClass(), this.path = findPath(AnnotationUtils.findAnnotation(this.config.getClass(),
ApplicationPath.class)); ApplicationPath.class));
} }
@ -78,9 +80,9 @@ public class JerseyAutoConfiguration implements WebApplicationInitializer {
@Bean @Bean
@ConditionalOnMissingBean(name = "jerseyServletRegistration") @ConditionalOnMissingBean(name = "jerseyServletRegistration")
public ServletRegistrationBean jerseyServletRegistration() { public ServletRegistrationBean jerseyServletRegistration() {
Class<? extends ResourceConfig> configType = config.getClass(); Class<? extends ResourceConfig> configType = this.config.getClass();
ServletRegistrationBean registration = new ServletRegistrationBean( ServletRegistrationBean registration = new ServletRegistrationBean(
new ServletContainer(), path); new ServletContainer(), this.path);
registration.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, registration.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS,
configType.getName()); configType.getName());
registration.setName("jerseyServlet"); registration.setName("jerseyServlet");
@ -100,7 +102,7 @@ public class JerseyAutoConfiguration implements WebApplicationInitializer {
return "/*"; return "/*";
} }
String path = annotation.value(); String path = annotation.value();
return path.isEmpty() || path.equals("/") ? "/*" : path + "/*"; return ((path.isEmpty() || path.equals("/")) ? "/*" : path + "/*");
} }
} }

@ -29,6 +29,7 @@ import org.springframework.transaction.jta.JtaTransactionManager;
* JTA Configuration for a JNDI-managed {@link JtaTransactionManager}. * JTA Configuration for a JNDI-managed {@link JtaTransactionManager}.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Stephane Nicoll
* @since 1.2.0 * @since 1.2.0
*/ */
@Configuration @Configuration
@ -41,8 +42,7 @@ class JndiJtaConfiguration {
@Bean @Bean
public JtaTransactionManager transactionManager() { public JtaTransactionManager transactionManager() {
JtaTransactionManagerFactoryBean factoryBean = new JtaTransactionManagerFactoryBean(); return new JtaTransactionManagerFactoryBean().getObject();
return factoryBean.getObject();
} }
} }

@ -22,8 +22,6 @@ import java.util.Map;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -37,6 +35,8 @@ import org.springframework.boot.orm.jpa.hibernate.SpringJtaPlatform;
import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter; import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
@ -50,6 +50,7 @@ import org.springframework.util.ClassUtils;
* *
* @author Phillip Webb * @author Phillip Webb
* @author Josh Long * @author Josh Long
* @author Manuel Doninger
*/ */
@Configuration @Configuration
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, @ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class,
@ -60,8 +61,12 @@ public class HibernateJpaAutoConfiguration extends JpaBaseConfiguration {
private static final String JTA_PLATFORM = "hibernate.transaction.jta.platform"; private static final String JTA_PLATFORM = "hibernate.transaction.jta.platform";
private static final Logger logger = LoggerFactory /**
.getLogger(HibernateJpaAutoConfiguration.class); * {@code NoJtaPlatform} implementations for various Hibernate versions.
*/
private static final String NO_JTA_PLATFORM_CLASSES[] = {
"org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform",
"org.hibernate.service.jta.platform.internal.NoJtaPlatform" };
@Autowired @Autowired
private JpaProperties properties; private JpaProperties properties;
@ -84,38 +89,35 @@ public class HibernateJpaAutoConfiguration extends JpaBaseConfiguration {
@Override @Override
protected void customizeVendorProperties(Map<String, Object> vendorProperties) { protected void customizeVendorProperties(Map<String, Object> vendorProperties) {
super.customizeVendorProperties(vendorProperties); super.customizeVendorProperties(vendorProperties);
if (!vendorProperties.containsKey(JTA_PLATFORM)) {
dunno(vendorProperties);
}
}
String HIBERNATE43_NOJTAPLATFORM_CLASS = "org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform"; private void dunno(Map<String, Object> vendorProperties) throws LinkageError {
String HIBERNATE42_NOJTAPLATFORM_CLASS = "org.hibernate.service.jta.platform.internal.NoJtaPlatform"; JtaTransactionManager jtaTransactionManager = getJtaTransactionManager();
if (jtaTransactionManager != null) {
vendorProperties.put(JTA_PLATFORM, new SpringJtaPlatform(
jtaTransactionManager));
}
else {
vendorProperties.put(JTA_PLATFORM, getNoJtaPlatformManager());
}
}
if (!vendorProperties.containsKey(JTA_PLATFORM)) { private Object getNoJtaPlatformManager() {
JtaTransactionManager jtaTransactionManager = getJtaTransactionManager(); for (String noJtaPlatformClass : NO_JTA_PLATFORM_CLASSES) {
try { try {
if (jtaTransactionManager != null) { return Class.forName(noJtaPlatformClass).newInstance();
vendorProperties.put(JTA_PLATFORM, new SpringJtaPlatform(
jtaTransactionManager));
}
else {
Object jtaPlatform = null;
if (ClassUtils.isPresent(HIBERNATE43_NOJTAPLATFORM_CLASS, null)) {
jtaPlatform = ClassUtils.forName(HIBERNATE43_NOJTAPLATFORM_CLASS,
null).newInstance();
}
else if (ClassUtils.isPresent(HIBERNATE42_NOJTAPLATFORM_CLASS, null)) {
jtaPlatform = ClassUtils.forName(HIBERNATE42_NOJTAPLATFORM_CLASS,
null).newInstance();
}
if (jtaPlatform != null) {
vendorProperties.put(JTA_PLATFORM, jtaPlatform);
}
}
} }
catch (Exception e) { catch (Exception ex) {
logger.error("Could not configure the JTA platform", e); // Continue searching
} }
} }
throw new IllegalStateException("Could not configure JTA platform");
} }
@Order(Ordered.HIGHEST_PRECEDENCE + 20)
static class HibernateEntityManagerCondition extends SpringBootCondition { static class HibernateEntityManagerCondition extends SpringBootCondition {
private static String[] CLASS_NAMES = { private static String[] CLASS_NAMES = {

@ -45,8 +45,8 @@ import com.google.gson.Gson;
* @author Piotr Maj * @author Piotr Maj
* @author Oliver Gierke * @author Oliver Gierke
* @author David Liu * @author David Liu
* @author Sebastien Deleuze
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Sebastien Deleuze
*/ */
@Configuration @Configuration
@ConditionalOnClass(HttpMessageConverter.class) @ConditionalOnClass(HttpMessageConverter.class)

@ -60,9 +60,9 @@ import static org.mockito.Mockito.verify;
* *
* @author Dave Syer * @author Dave Syer
* @author Oliver Gierke * @author Oliver Gierke
* @author Sebastien Deleuze
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Marcel Overdijk * @author Marcel Overdijk
* @author Sebastien Deleuze
*/ */
public class JacksonAutoConfigurationTests { public class JacksonAutoConfigurationTests {

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,8 +16,6 @@
package org.springframework.boot.autoconfigure.jersey; package org.springframework.boot.autoconfigure.jersey;
import static org.junit.Assert.assertEquals;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -34,7 +32,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.jersey.CustomServletPathTests.Application; import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfigurationCustomServletPathTests.Application;
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration; import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration; import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration;
import org.springframework.boot.test.IntegrationTest; import org.springframework.boot.test.IntegrationTest;
@ -47,20 +45,28 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import static org.junit.Assert.assertEquals;
/**
* Tests for {@link JerseyAutoConfiguration} when using custom servlet paths.
*
* @author Dave Syer
*/
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class) @SpringApplicationConfiguration(classes = Application.class)
@IntegrationTest("server.port=0") @IntegrationTest("server.port=0")
@WebAppConfiguration @WebAppConfiguration
public class CustomServletPathTests { public class JerseyAutoConfigurationCustomServletPathTests {
@Value("${local.server.port}") @Value("${local.server.port}")
private int port; private int port;
private RestTemplate restTemplate = new TestRestTemplate(); private RestTemplate restTemplate = new TestRestTemplate();
@Test @Test
public void contextLoads() { public void contextLoads() {
ResponseEntity<String> entity = restTemplate.getForEntity("http://localhost:" + port + "/rest/hello", String.class); ResponseEntity<String> entity = this.restTemplate.getForEntity(
"http://localhost:" + this.port + "/rest/hello", String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode()); assertEquals(HttpStatus.OK, entity.getStatusCode());
} }
@ -71,10 +77,10 @@ public class CustomServletPathTests {
@Value("${message:World}") @Value("${message:World}")
private String msg; private String msg;
@GET @GET
public String message() { public String message() {
return "Hello " + msg; return "Hello " + this.msg;
} }
public Application() { public Application() {

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,8 +16,6 @@
package org.springframework.boot.autoconfigure.jersey; package org.springframework.boot.autoconfigure.jersey;
import static org.junit.Assert.assertEquals;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -33,7 +31,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.jersey.DefaultServletPathTests.Application; import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfigurationDefaultServletPathTests.Application;
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration; import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration; import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration;
import org.springframework.boot.test.IntegrationTest; import org.springframework.boot.test.IntegrationTest;
@ -46,11 +44,18 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import static org.junit.Assert.assertEquals;
/**
* Tests for {@link JerseyAutoConfiguration} when using default servlet paths.
*
* @author Dave Syer
*/
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class) @SpringApplicationConfiguration(classes = Application.class)
@IntegrationTest("server.port=0") @IntegrationTest("server.port=0")
@WebAppConfiguration @WebAppConfiguration
public class DefaultServletPathTests { public class JerseyAutoConfigurationDefaultServletPathTests {
@Value("${local.server.port}") @Value("${local.server.port}")
private int port; private int port;
@ -59,8 +64,8 @@ public class DefaultServletPathTests {
@Test @Test
public void contextLoads() { public void contextLoads() {
ResponseEntity<String> entity = restTemplate.getForEntity("http://localhost:" ResponseEntity<String> entity = this.restTemplate.getForEntity(
+ port + "/hello", String.class); "http://localhost:" + this.port + "/hello", String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode()); assertEquals(HttpStatus.OK, entity.getStatusCode());
} }
@ -77,7 +82,7 @@ public class DefaultServletPathTests {
@GET @GET
public String message() { public String message() {
return "Hello " + msg; return "Hello " + this.msg;
} }
public static void main(String[] args) { public static void main(String[] args) {

@ -1031,59 +1031,60 @@ upon successful completion of a servlet's service method. You should disable th
behaviour by setting `com.ibm.ws.webcontainer.invokeFlushAfterService` to `false` behaviour by setting `com.ibm.ws.webcontainer.invokeFlushAfterService` to `false`
[[boot-features-jersey]] [[boot-features-jersey]]
=== JAX-RS and Jersey === JAX-RS and Jersey
If you prefer the JAX-RS programming model for REST endpoints you can use one of the If you prefer the JAX-RS programming model for REST endpoints you can use one of the
available implementations instead of Spring MVC. Jersey 1.x and Apache Celtix work available implementations instead of Spring MVC. Jersey 1.x and Apache Celtix work
quite well out of the box if you just register their `Servlet` or `Filter` as a quite well out of the box if you just register their `Servlet` or `Filter` as a
`@Bean` in your application context. Jersey 2.x has some native Spring support so `@Bean` in your application context. Jersey 2.x has some native Spring support so
we also provide autoconfiguration support for it in Spring Boot together with a we also provide autoconfiguration support for it in Spring Boot together with a
starter. starter.
To get started with Jersey 2.x just include the `spring-boot-starter-jersey` as a dependency To get started with Jersey 2.x just include the `spring-boot-starter-jersey` as a
and then you need one `@Bean` of type `ResourceConfig` in which you register all the dependency and then you need one `@Bean` of type `ResourceConfig` in which you register
endpoints: all the endpoints:
[source,java] [source,java,indent=0,subs="verbatim,quotes,attributes"]
---- ----
@Component @Component
public class JerseyConfig extends ResourceConfig { public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
public JerseyConfig() { register(Endpoint.class);
register(Endpoint.class); }
} }
}
---- ----
All the registered endpoints should be `@Components` with HTTP resource annotations (`@GET` etc.), e.g. All the registered endpoints should be `@Components` with HTTP resource annotations
(`@GET` etc.), e.g.
[source,java] [source,java,indent=0,subs="verbatim,quotes,attributes"]
---- ----
@Component @Component
@Path("/hello") @Path("/hello")
public class Endpoint { public class Endpoint {
@GET @GET
public String message() { public String message() {
return "Hello"; return "Hello";
} }
} }
---- ----
Since the `Endpoint` is a Spring `@Component` its lifecycle Since the `Endpoint` is a Spring `@Component` its lifecycle is managed by Spring and you
is managed by Spring and you can `@Autowired` dependencies and inject can `@Autowired` dependencies and inject external configuration with `@Value`. The Jersey
external configuration with `@Value`. The Jersey servlet will be servlet will be registered and mapped to ``/\*'' by default. You can change the mapping
registered and mapped to "/\*" by default. You can change the mapping
by adding `@ApplicationPath` to your `ResourceConfig`. by adding `@ApplicationPath` to your `ResourceConfig`.
There is a {github-code}/spring-boot-samples/spring-boot-sample-jersey[Jersey sample] so There is a {github-code}/spring-boot-samples/spring-boot-sample-jersey[Jersey sample] so
you can see how to set things up. There is also a {github-code}/spring-boot-samples/spring-boot-sample-jersey1[Jersey 1.x sample]. you can see how to set things up. There is also a {github-code}/spring-boot-samples/spring-boot-sample-jersey1[Jersey 1.x sample].
Note that in the Jersey 1.x sample that the spring-boot maven plugin has been configured to Note that in the Jersey 1.x sample that the spring-boot maven plugin has been configured to
unpack some Jersey jars so they can be scanned by the JAX-RS implementation (the sample unpack some Jersey jars so they can be scanned by the JAX-RS implementation (the sample
asks for them to be scanned in its `Filter` registration. asks for them to be scanned in its `Filter` registration.
[[boot-features-embedded-container]] [[boot-features-embedded-container]]
=== Embedded servlet container support === Embedded servlet container support
Spring Boot includes support for embedded Tomcat and Jetty servers. Most developers will Spring Boot includes support for embedded Tomcat and Jetty servers. Most developers will

@ -1,22 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?> <?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" <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">
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> <modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-sample-jersey</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<packaging>war</packaging>
<name>spring-boot-sample-jersey</name>
<description>Spring Boot Jersey sample project</description>
<parent> <parent>
<!-- Your own application should inherit from spring-boot-starter-parent --> <!-- Your own application should inherit from spring-boot-starter-parent -->
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-samples</artifactId> <artifactId>spring-boot-samples</artifactId>
<version>1.2.0.BUILD-SNAPSHOT</version> <version>1.2.0.BUILD-SNAPSHOT</version>
</parent> </parent>
<artifactId>spring-boot-sample-jersey</artifactId>
<packaging>war</packaging>
<name>Spring Boot Jersey Sample</name>
<description>Spring Boot Jersey 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> <dependencies>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -28,7 +30,6 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
@ -37,5 +38,4 @@
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,10 +22,6 @@ import javax.ws.rs.Path;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/**
* @author Dave Syer
*
*/
@Component @Component
@Path("/hello") @Path("/hello")
public class Endpoint { public class Endpoint {
@ -35,7 +31,7 @@ public class Endpoint {
@GET @GET
public String message() { public String message() {
return "Hello " + msg; return "Hello " + this.msg;
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -31,8 +31,8 @@ public class SampleJerseyApplication extends SpringBootServletInitializer {
} }
public static void main(String[] args) { public static void main(String[] args) {
new SampleJerseyApplication().configure(new SpringApplicationBuilder(SampleJerseyApplication.class)).run( new SampleJerseyApplication().configure(
args); new SpringApplicationBuilder(SampleJerseyApplication.class)).run(args);
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,8 +16,6 @@
package sample.jersey; package sample.jersey;
import static org.junit.Assert.assertEquals;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -30,21 +28,23 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleJerseyApplication.class) @SpringApplicationConfiguration(classes = SampleJerseyApplication.class)
@IntegrationTest("server.port=0") @IntegrationTest("server.port=0")
@WebAppConfiguration @WebAppConfiguration
public class SampleJerseyApplicationTests { public class SampleJerseyApplicationTests {
@Value("${local.server.port}") @Value("${local.server.port}")
private int port; private int port;
private RestTemplate restTemplate =new TestRestTemplate(); private RestTemplate restTemplate = new TestRestTemplate();
@Test @Test
public void contextLoads() { public void contextLoads() {
ResponseEntity<String> entity = restTemplate.getForEntity("http://localhost:" ResponseEntity<String> entity = this.restTemplate.getForEntity(
+ port + "/hello", String.class); "http://localhost:" + this.port + "/hello", String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode()); assertEquals(HttpStatus.OK, entity.getStatusCode());
} }

@ -1,22 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?> <?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" <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">
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> <modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-sample-jersey1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-boot-sample-jersey1</name>
<description>Spring Boot Sample with Jersey 1.x</description>
<parent> <parent>
<!-- Your own application should inherit from spring-boot-starter-parent --> <!-- Your own application should inherit from spring-boot-starter-parent -->
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-samples</artifactId> <artifactId>spring-boot-samples</artifactId>
<version>1.2.0.BUILD-SNAPSHOT</version> <version>1.2.0.BUILD-SNAPSHOT</version>
</parent> </parent>
<artifactId>spring-boot-sample-jersey1</artifactId>
<name>Spring Boot Jersey 1 Sample</name>
<description>Spring Boot Jersey 1 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> <dependencies>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -41,7 +42,6 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
@ -66,5 +66,4 @@
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

@ -1,3 +1,19 @@
/*
* 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.jersey1; package sample.jersey1;
import javax.ws.rs.GET; import javax.ws.rs.GET;
@ -20,28 +36,29 @@ import com.sun.jersey.spi.container.servlet.ServletContainer;
@Path("/") @Path("/")
public class SampleJersey1Application { public class SampleJersey1Application {
public static void main(String[] args) { @GET
new SpringApplicationBuilder(SampleJersey1Application.class).web(true).run(args); @Produces("text/plain")
} public String hello() {
return "Hello World";
@GET }
@Produces("text/plain")
public String hello() { @Bean
return "Hello World"; // Not needed if Spring Web MVC is also present on claspath
} public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory();
@Bean }
// Not needed if Spring Web MVC is also present on claspath
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() { @Bean
return new TomcatEmbeddedServletContainerFactory(); public FilterRegistrationBean jersey() {
} FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new ServletContainer());
@Bean bean.addInitParameter("com.sun.jersey.config.property.packages",
public FilterRegistrationBean jersey() { "com.sun.jersey;sample.jersey1");
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new ServletContainer());
bean.addInitParameter("com.sun.jersey.config.property.packages", "com.sun.jersey;sample.jersey1");
return bean; return bean;
} }
public static void main(String[] args) {
new SpringApplicationBuilder(SampleJersey1Application.class).web(true).run(args);
}
} }

@ -1,30 +1,45 @@
package sample.jersey1; /*
* 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.
*/
import static org.junit.Assert.assertEquals; package sample.jersey1;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.IntegrationTest; import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate; import org.springframework.boot.test.TestRestTemplate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import sample.jersey1.SampleJersey1Application; import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleJersey1Application.class) @SpringApplicationConfiguration(classes = SampleJersey1Application.class)
@WebAppConfiguration @WebAppConfiguration
@IntegrationTest("server.port:0") @IntegrationTest("server.port:0")
public class SampleJersey1ApplicationTests { public class SampleJersey1ApplicationTests {
@Value("${local.server.port}") @Value("${local.server.port}")
private int port; private int port;
@Test @Test
public void contextLoads() { public void contextLoads() {
assertEquals("Hello World", new TestRestTemplate().getForObject("http://localhost:" + port + "/", String.class)); assertEquals("Hello World", new TestRestTemplate().getForObject(
"http://localhost:" + this.port + "/", String.class));
} }
} }

Loading…
Cancel
Save