Commit c34cfb27 authored by Phillip Webb's avatar Phillip Webb

Polish

parent b53d72e9
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.springframework.boot.actuate.endpoint; package org.springframework.boot.actuate.endpoint;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
...@@ -286,6 +287,9 @@ public class ConfigurationPropertiesReportEndpoint extends ...@@ -286,6 +287,9 @@ public class ConfigurationPropertiesReportEndpoint extends
} }
/**
* {@link BeanSerializerModifier} to return only relevant configuration properties.
*/
protected static class GenericSerializerModifier extends BeanSerializerModifier { protected static class GenericSerializerModifier extends BeanSerializerModifier {
@Override @Override
...@@ -302,7 +306,7 @@ public class ConfigurationPropertiesReportEndpoint extends ...@@ -302,7 +306,7 @@ public class ConfigurationPropertiesReportEndpoint extends
} }
private boolean isReadable(BeanDescription beanDesc, BeanPropertyWriter writer) { private boolean isReadable(BeanDescription beanDesc, BeanPropertyWriter writer) {
String parenType = beanDesc.getType().getRawClass().getName(); String parentType = beanDesc.getType().getRawClass().getName();
String type = writer.getPropertyType().getName(); String type = writer.getPropertyType().getName();
AnnotatedMethod setter = beanDesc.findMethod( AnnotatedMethod setter = beanDesc.findMethod(
"set" + StringUtils.capitalize(writer.getName()), "set" + StringUtils.capitalize(writer.getName()),
...@@ -312,10 +316,9 @@ public class ConfigurationPropertiesReportEndpoint extends ...@@ -312,10 +316,9 @@ public class ConfigurationPropertiesReportEndpoint extends
// that its a nested class used solely for binding to config props, so it // that its a nested class used solely for binding to config props, so it
// should be kosher. This filter is not used if there is JSON metadata for // should be kosher. This filter is not used if there is JSON metadata for
// the property, so it's mainly for user-defined beans. // the property, so it's mainly for user-defined beans.
boolean readable = setter != null return (setter != null)
|| ClassUtils.getPackageName(parenType).equals( || ClassUtils.getPackageName(parentType).equals(
ClassUtils.getPackageName(type)); ClassUtils.getPackageName(type));
return readable;
} }
} }
...@@ -327,9 +330,11 @@ public class ConfigurationPropertiesReportEndpoint extends ...@@ -327,9 +330,11 @@ public class ConfigurationPropertiesReportEndpoint extends
*/ */
protected static class ConfigurationPropertiesMetaData { protected static class ConfigurationPropertiesMetaData {
private Map<String, Set<String>> matched = new HashMap<String, Set<String>>(); private final String metadataLocations;
private final Map<String, Set<String>> matched = new HashMap<String, Set<String>>();
private Set<String> keys = null; private Set<String> keys = null;
private String metadataLocations;
public ConfigurationPropertiesMetaData(String metadataLocations) { public ConfigurationPropertiesMetaData(String metadataLocations) {
this.metadataLocations = metadataLocations; this.metadataLocations = metadataLocations;
...@@ -349,53 +354,45 @@ public class ConfigurationPropertiesReportEndpoint extends ...@@ -349,53 +354,45 @@ public class ConfigurationPropertiesReportEndpoint extends
} }
private boolean matchesInternal(String prefix) { private boolean matchesInternal(String prefix) {
if (this.matched.get(prefix) != null) { return this.matched.get(prefix) != null;
return true;
}
else {
return false;
}
} }
private Set<String> findKeys(String prefix) { private Set<String> findKeys(String prefix) {
HashSet<String> keys = new HashSet<String>();
HashSet<String> set = new HashSet<String>(); for (String key : getKeys()) {
try {
if (this.keys == null) {
this.keys = new HashSet<String>();
ObjectMapper mapper = new ObjectMapper();
Resource[] resources = new PathMatchingResourcePatternResolver()
.getResources(this.metadataLocations);
for (Resource resource : resources) {
addKeys(mapper, resource);
}
}
}
catch (IOException e) {
logger.warn("Could not deserialize config properties metadata", e);
}
for (String key : this.keys) {
if (key.length() > prefix.length() if (key.length() > prefix.length()
&& key.startsWith(prefix) && key.startsWith(prefix)
&& ".".equals(key.substring(prefix.length(), prefix.length() + 1))) { && ".".equals(key.substring(prefix.length(), prefix.length() + 1))) {
set.add(key.substring(prefix.length() + 1)); keys.add(key.substring(prefix.length() + 1));
}
}
return (keys.isEmpty() ? null : keys);
}
private Set<String> getKeys() {
if (this.keys != null) {
return this.keys;
}
this.keys = new HashSet<String>();
try {
ObjectMapper mapper = new ObjectMapper();
Resource[] resources = new PathMatchingResourcePatternResolver()
.getResources(this.metadataLocations);
for (Resource resource : resources) {
addKeys(mapper, resource);
} }
} }
if (set.isEmpty()) { catch (IOException ex) {
return null; logger.warn("Could not deserialize config properties metadata", ex);
} }
return set; return this.keys;
} }
@SuppressWarnings("unchecked")
private void addKeys(ObjectMapper mapper, Resource resource) throws IOException, private void addKeys(ObjectMapper mapper, Resource resource) throws IOException,
JsonParseException, JsonMappingException { JsonParseException, JsonMappingException {
@SuppressWarnings("unchecked") InputStream inputStream = resource.getInputStream();
Map<String, Object> map = mapper.readValue(resource.getInputStream(), Map<String, Object> map = mapper.readValue(inputStream, Map.class);
Map.class);
@SuppressWarnings("unchecked")
Collection<Map<String, Object>> metadata = (Collection<Map<String, Object>>) map Collection<Map<String, Object>> metadata = (Collection<Map<String, Object>>) map
.get("properties"); .get("properties");
for (Map<String, Object> value : metadata) { for (Map<String, Object> value : metadata) {
...@@ -404,8 +401,8 @@ public class ConfigurationPropertiesReportEndpoint extends ...@@ -404,8 +401,8 @@ public class ConfigurationPropertiesReportEndpoint extends
this.keys.add((String) value.get("name")); this.keys.add((String) value.get("name"));
} }
} }
catch (Exception e) { catch (Exception ex) {
logger.warn("Could not parse config properties metadata", e); logger.warn("Could not parse config properties metadata", ex);
} }
} }
} }
...@@ -421,13 +418,13 @@ public class ConfigurationPropertiesReportEndpoint extends ...@@ -421,13 +418,13 @@ public class ConfigurationPropertiesReportEndpoint extends
return map; return map;
} }
@SuppressWarnings("unchecked")
private void addProperty(Object bean, String key, Map<String, Object> map) { private void addProperty(Object bean, String key, Map<String, Object> map) {
String prefix = key.contains(".") ? StringUtils.split(key, ".")[0] : key; String prefix = (key.contains(".") ? StringUtils.split(key, ".")[0] : key);
String suffix = key.length() > prefix.length() ? key.substring(prefix String suffix = (key.length() > prefix.length() ? key.substring(prefix
.length() + 1) : null; .length() + 1) : null);
String property = prefix; String property = prefix;
if (bean instanceof Map) { if (bean instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> value = (Map<String, Object>) bean; Map<String, Object> value = (Map<String, Object>) bean;
bean = new MapHolder(value); bean = new MapHolder(value);
property = "map[" + property + "]"; property = "map[" + property + "]";
...@@ -446,14 +443,15 @@ public class ConfigurationPropertiesReportEndpoint extends ...@@ -446,14 +443,15 @@ public class ConfigurationPropertiesReportEndpoint extends
map.put(prefix, value); map.put(prefix, value);
} }
} }
catch (Exception e) { catch (Exception ex) {
// Probably just lives on a different bean (it happens) // Probably just lives on a different bean (it happens)
logger.debug("Could not parse config properties metadata '" + key + "': " logger.debug("Could not parse config properties metadata '" + key + "': "
+ e.getMessage()); + ex.getMessage());
} }
} }
protected static class MapHolder { protected static class MapHolder {
Map<String, Object> map = new HashMap<String, Object>(); Map<String, Object> map = new HashMap<String, Object>();
public MapHolder(Map<String, Object> bean) { public MapHolder(Map<String, Object> bean) {
...@@ -467,6 +465,7 @@ public class ConfigurationPropertiesReportEndpoint extends ...@@ -467,6 +465,7 @@ public class ConfigurationPropertiesReportEndpoint extends
public void setMap(Map<String, Object> map) { public void setMap(Map<String, Object> map) {
this.map = map; this.map = map;
} }
} }
} }
......
...@@ -20,9 +20,14 @@ package org.springframework.boot.actuate.endpoint.mvc; ...@@ -20,9 +20,14 @@ package org.springframework.boot.actuate.endpoint.mvc;
* Callback for customizing the {@link EndpointHandlerMapping} at configuration time. * Callback for customizing the {@link EndpointHandlerMapping} at configuration time.
* *
* @author Dave Syer * @author Dave Syer
* @since 1.2.0
*/ */
public interface EndpointHandlerMappingCustomizer { public interface EndpointHandlerMappingCustomizer {
/**
* Customize the specified {@link EndpointHandlerMapping}
* @param mapping the {@link EndpointHandlerMapping} to customize
*/
void customize(EndpointHandlerMapping mapping); void customize(EndpointHandlerMapping mapping);
} }
...@@ -97,6 +97,7 @@ public class EndpointMvcIntegrationTests { ...@@ -97,6 +97,7 @@ public class EndpointMvcIntegrationTests {
HttpMessageConvertersAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class }) ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class })
protected static @interface MinimalWebConfiguration { protected static @interface MinimalWebConfiguration {
} }
@Configuration @Configuration
...@@ -134,9 +135,11 @@ public class EndpointMvcIntegrationTests { ...@@ -134,9 +135,11 @@ public class EndpointMvcIntegrationTests {
protected TestInterceptor interceptor() { protected TestInterceptor interceptor() {
return new TestInterceptor(); return new TestInterceptor();
} }
} }
protected static class TestInterceptor extends HandlerInterceptorAdapter { protected static class TestInterceptor extends HandlerInterceptorAdapter {
private int count = 0; private int count = 0;
@Override @Override
...@@ -148,6 +151,7 @@ public class EndpointMvcIntegrationTests { ...@@ -148,6 +151,7 @@ public class EndpointMvcIntegrationTests {
public int getCount() { public int getCount() {
return this.count; return this.count;
} }
} }
} }
...@@ -471,6 +471,7 @@ public class EndpointWebMvcAutoConfigurationTests { ...@@ -471,6 +471,7 @@ public class EndpointWebMvcAutoConfigurationTests {
public EmbeddedServletContainer getServletContainer() { public EmbeddedServletContainer getServletContainer() {
return this.servletContainer; return this.servletContainer;
} }
} }
} }
...@@ -36,8 +36,8 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore; ...@@ -36,8 +36,8 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 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.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration; import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.boot.context.embedded.FilterRegistrationBean;
...@@ -98,7 +98,7 @@ public class JerseyAutoConfiguration implements WebApplicationInitializer { ...@@ -98,7 +98,7 @@ public class JerseyAutoConfiguration implements WebApplicationInitializer {
@Bean @Bean
@ConditionalOnMissingBean(name = "jerseyFilterRegistration") @ConditionalOnMissingBean(name = "jerseyFilterRegistration")
@ConditionalOnExpression("'${spring.jersey.type:servlet}' == 'filter'") @ConditionalOnProperty(prefix = "spring.jersey", name = "type", havingValue = "filter")
public FilterRegistrationBean jerseyFilterRegistration() { public FilterRegistrationBean jerseyFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean(); FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new ServletContainer()); registration.setFilter(new ServletContainer());
...@@ -121,7 +121,7 @@ public class JerseyAutoConfiguration implements WebApplicationInitializer { ...@@ -121,7 +121,7 @@ public class JerseyAutoConfiguration implements WebApplicationInitializer {
@Bean @Bean
@ConditionalOnMissingBean(name = "jerseyServletRegistration") @ConditionalOnMissingBean(name = "jerseyServletRegistration")
@ConditionalOnExpression("'${spring.jersey.type:servlet}' == 'servlet'") @ConditionalOnProperty(prefix = "spring.jersey", name = "type", havingValue = "servlet", matchIfMissing = true)
public ServletRegistrationBean jerseyServletRegistration() { public ServletRegistrationBean jerseyServletRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean( ServletRegistrationBean registration = new ServletRegistrationBean(
new ServletContainer(), this.path); new ServletContainer(), this.path);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.autoconfigure.jersey; package org.springframework.boot.autoconfigure.jersey;
import java.util.HashMap; import java.util.HashMap;
...@@ -21,17 +22,15 @@ import java.util.Map; ...@@ -21,17 +22,15 @@ import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
/** /**
* @author Dave Syer * {@link ConfigurationProperties} for Jersey.
* *
* @author Dave Syer
* @since 1.2.0
*/ */
@ConfigurationProperties("spring.jersey") @ConfigurationProperties("spring.jersey")
public class JerseyProperties { public class JerseyProperties {
public enum Type { private Type type = Type.SERVLET;
servlet, filter;
}
private Type type = Type.servlet;
private Map<String, String> init = new HashMap<String, String>(); private Map<String, String> init = new HashMap<String, String>();
...@@ -61,6 +60,10 @@ public class JerseyProperties { ...@@ -61,6 +60,10 @@ public class JerseyProperties {
this.init = init; this.init = init;
} }
public enum Type {
SERVLET, FILTER;
}
public static class Filter { public static class Filter {
private int order; private int order;
......
...@@ -46,8 +46,8 @@ import org.springframework.boot.context.properties.NestedConfigurationProperty; ...@@ -46,8 +46,8 @@ import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
* {@link ConfigurationProperties properties} for a web server (e.g. port and path * {@link ConfigurationProperties} for a web server (e.g. port and path settings). Will be
* settings). Will be used to customize an {@link EmbeddedServletContainerFactory} when an * used to customize an {@link EmbeddedServletContainerFactory} when an
* {@link EmbeddedServletContainerCustomizerBeanPostProcessor} is active. * {@link EmbeddedServletContainerCustomizerBeanPostProcessor} is active.
* *
* @author Dave Syer * @author Dave Syer
......
/*
* 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 org.springframework.boot.autoconfigure.websocket;
import org.eclipse.jetty.webapp.AbstractConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
/**
* {@link WebSocketContainerCustomizer} for {@link JettyEmbeddedServletContainerFactory}.
*
* @author Dave Syer
* @author Phillip Webb
* @author Andy Wilkinson
* @since 1.2.0
*/
public class JettyWebSocketContainerCustomizer extends
WebSocketContainerCustomizer<JettyEmbeddedServletContainerFactory> {
@Override
protected void doCustomize(JettyEmbeddedServletContainerFactory container) {
container.addConfigurations(new AbstractConfiguration() {
@Override
public void configure(WebAppContext context) throws Exception {
WebSocketServerContainerInitializer.configureContext(context);
}
});
}
}
/*
* 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 org.springframework.boot.autoconfigure.websocket;
import java.lang.reflect.Constructor;
import org.apache.catalina.Context;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
* {@link WebSocketContainerCustomizer} for {@link TomcatEmbeddedServletContainerFactory}.
*
* @author Dave Syer
* @author Phillip Webb
* @author Andy Wilkinson
* @since 1.2.0
*/
public class TomcatWebSocketContainerCustomizer extends
WebSocketContainerCustomizer<TomcatEmbeddedServletContainerFactory> {
private static final String TOMCAT_7_LISTENER_TYPE = "org.apache.catalina.deploy.ApplicationListener";
private static final String TOMCAT_8_LISTENER_TYPE = "org.apache.tomcat.util.descriptor.web.ApplicationListener";
private static final String WS_LISTENER = "org.apache.tomcat.websocket.server.WsContextListener";
@Override
public void doCustomize(TomcatEmbeddedServletContainerFactory tomcatContainer) {
tomcatContainer.addContextCustomizers(new TomcatContextCustomizer() {
@Override
public void customize(Context context) {
addListener(context, findListenerType());
}
});
}
private Class<?> findListenerType() {
if (ClassUtils.isPresent(TOMCAT_7_LISTENER_TYPE, null)) {
return ClassUtils.resolveClassName(TOMCAT_7_LISTENER_TYPE, null);
}
if (ClassUtils.isPresent(TOMCAT_8_LISTENER_TYPE, null)) {
return ClassUtils.resolveClassName(TOMCAT_8_LISTENER_TYPE, null);
}
// With Tomcat 8.0.8 ApplicationListener is not required
return null;
}
/**
* Instead of registering the WsSci directly as a ServletContainerInitializer, we use
* the ApplicationListener provided by Tomcat. Unfortunately the ApplicationListener
* class moved packages in Tomcat 8 and been deleted in 8.0.8 so we have to use
* reflection.
* @param context the current context
* @param listenerType the type of listener to add
*/
private void addListener(Context context, Class<?> listenerType) {
Class<? extends Context> contextClass = context.getClass();
if (listenerType == null) {
ReflectionUtils.invokeMethod(ClassUtils.getMethod(contextClass,
"addApplicationListener", String.class), context, WS_LISTENER);
}
else {
Constructor<?> constructor = ClassUtils.getConstructorIfAvailable(
listenerType, String.class, boolean.class);
Object instance = BeanUtils.instantiateClass(constructor, WS_LISTENER, false);
ReflectionUtils.invokeMethod(ClassUtils.getMethod(contextClass,
"addApplicationListener", listenerType), context, instance);
}
}
}
...@@ -18,39 +18,26 @@ package org.springframework.boot.autoconfigure.websocket; ...@@ -18,39 +18,26 @@ package org.springframework.boot.autoconfigure.websocket;
import javax.servlet.Servlet; import javax.servlet.Servlet;
import org.apache.catalina.Context;
import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.Tomcat;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.webapp.AbstractConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer; import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.AutoConfigureBefore;
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;
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration; import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.boot.context.web.NonEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
/** /**
* Auto configuration for websocket server in embedded Tomcat or Jetty. Requires * Auto configuration for websocket server in embedded Tomcat or Jetty. Requires
* <code>spring-websocket</code> and either Tomcat or Jetty with their WebSocket modules * <code>spring-websocket</code> and either Tomcat or Jetty with their WebSocket modules
* to be on the classpath. * to be on the classpath.
* <p/> * <p>
* If Tomcat's WebSocket support is detected on the classpath we add a listener that * If Tomcat's WebSocket support is detected on the classpath we add a listener that
* installs the Tomcat Websocket initializer. In a non-embedded container it should * installs the Tomcat Websocket initializer. In a non-embedded container it should
* already be there. * already be there.
* <p/> * <p>
* If Jetty's WebSocket support is detected on the classpath we add a configuration that * If Jetty's WebSocket support is detected on the classpath we add a configuration that
* configures the context with WebSocket support. In a non-embedded container it should * configures the context with WebSocket support. In a non-embedded container it should
* already be there. * already be there.
...@@ -68,65 +55,12 @@ public class WebSocketAutoConfiguration { ...@@ -68,65 +55,12 @@ public class WebSocketAutoConfiguration {
@ConditionalOnClass(name = "org.apache.tomcat.websocket.server.WsSci", value = Tomcat.class) @ConditionalOnClass(name = "org.apache.tomcat.websocket.server.WsSci", value = Tomcat.class)
static class TomcatWebSocketConfiguration { static class TomcatWebSocketConfiguration {
private static final String TOMCAT_7_LISTENER_TYPE = "org.apache.catalina.deploy.ApplicationListener";
private static final String TOMCAT_8_LISTENER_TYPE = "org.apache.tomcat.util.descriptor.web.ApplicationListener";
private static final String WS_LISTENER = "org.apache.tomcat.websocket.server.WsContextListener";
@Bean @Bean
@ConditionalOnMissingBean(name = "websocketContainerCustomizer") @ConditionalOnMissingBean(name = "websocketContainerCustomizer")
public EmbeddedServletContainerCustomizer websocketContainerCustomizer() { public EmbeddedServletContainerCustomizer websocketContainerCustomizer() {
return new WebSocketContainerCustomizer<TomcatEmbeddedServletContainerFactory>( return new TomcatWebSocketContainerCustomizer();
TomcatEmbeddedServletContainerFactory.class) {
@Override
public void doCustomize(
TomcatEmbeddedServletContainerFactory tomcatContainer) {
tomcatContainer.addContextCustomizers(new TomcatContextCustomizer() {
@Override
public void customize(Context context) {
addListener(context, findListenerType());
}
});
}
};
}
private static Class<?> findListenerType() {
if (ClassUtils.isPresent(TOMCAT_7_LISTENER_TYPE, null)) {
return ClassUtils.resolveClassName(TOMCAT_7_LISTENER_TYPE, null);
}
if (ClassUtils.isPresent(TOMCAT_8_LISTENER_TYPE, null)) {
return ClassUtils.resolveClassName(TOMCAT_8_LISTENER_TYPE, null);
}
// With Tomcat 8.0.8 ApplicationListener is not required
return null;
} }
/**
* Instead of registering the WsSci directly as a ServletContainerInitializer, we
* use the ApplicationListener provided by Tomcat. Unfortunately the
* ApplicationListener class moved packages in Tomcat 8 and been deleted in 8.0.8
* so we have to use reflection.
* @param context the current context
* @param listenerType the type of listener to add
*/
private static void addListener(Context context, Class<?> listenerType) {
if (listenerType == null) {
ReflectionUtils.invokeMethod(ClassUtils.getMethod(context.getClass(),
"addApplicationListener", String.class), context, WS_LISTENER);
}
else {
Object instance = BeanUtils.instantiateClass(ClassUtils
.getConstructorIfAvailable(listenerType, String.class,
boolean.class), WS_LISTENER, false);
ReflectionUtils.invokeMethod(ClassUtils.getMethod(context.getClass(),
"addApplicationListener", listenerType), context, instance);
}
}
} }
@Configuration @Configuration
...@@ -136,53 +70,9 @@ public class WebSocketAutoConfiguration { ...@@ -136,53 +70,9 @@ public class WebSocketAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean(name = "websocketContainerCustomizer") @ConditionalOnMissingBean(name = "websocketContainerCustomizer")
public EmbeddedServletContainerCustomizer websocketContainerCustomizer() { public EmbeddedServletContainerCustomizer websocketContainerCustomizer() {
return new WebSocketContainerCustomizer<JettyEmbeddedServletContainerFactory>( return new JettyWebSocketContainerCustomizer();
JettyEmbeddedServletContainerFactory.class) {
@Override
protected void doCustomize(JettyEmbeddedServletContainerFactory container) {
container.addConfigurations(new AbstractConfiguration() {
@Override
public void configure(WebAppContext context) throws Exception {
WebSocketServerContainerInitializer.configureContext(context);
}
});
}
};
} }
} }
abstract static class WebSocketContainerCustomizer<T extends ConfigurableEmbeddedServletContainer>
implements EmbeddedServletContainerCustomizer {
private Log logger = LogFactory.getLog(getClass());
private final Class<T> containerType;
protected WebSocketContainerCustomizer(Class<T> containerType) {
this.containerType = containerType;
}
@SuppressWarnings("unchecked")
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof NonEmbeddedServletContainerFactory) {
this.logger
.info("NonEmbeddedServletContainerFactory detected. Websockets "
+ "support should be native so this normally is not a problem.");
return;
}
if (this.containerType.isAssignableFrom(container.getClass())) {
doCustomize((T) container);
}
}
protected abstract void doCustomize(T container);
}
} }
/*
* 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 org.springframework.boot.autoconfigure.websocket;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.web.NonEmbeddedServletContainerFactory;
import org.springframework.core.ResolvableType;
/**
* {@link EmbeddedServletContainerCustomizer} to configure websockets for a given
* {@link EmbeddedServletContainerFactory}.
*
* @author Dave Syer
* @author Phillip Webb
* @author Andy Wilkinson
* @since 1.2.0
*/
public abstract class WebSocketContainerCustomizer<T extends EmbeddedServletContainerFactory>
implements EmbeddedServletContainerCustomizer {
private Log logger = LogFactory.getLog(getClass());
@SuppressWarnings("unchecked")
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof NonEmbeddedServletContainerFactory) {
this.logger.info("NonEmbeddedServletContainerFactory "
+ "detected. Websockets support should be native so this "
+ "normally is not a problem.");
return;
}
if (getContainerType().isAssignableFrom(container.getClass())) {
doCustomize((T) container);
}
}
protected Class<?> getContainerType() {
return ResolvableType.forClass(WebSocketContainerCustomizer.class, getClass())
.resolveGeneric();
}
protected abstract void doCustomize(T container);
}
...@@ -134,7 +134,8 @@ class InitializrService { ...@@ -134,7 +134,8 @@ class InitializrService {
*/ */
private CloseableHttpResponse executeInitializrMetadataRetrieval(String url) { private CloseableHttpResponse executeInitializrMetadataRetrieval(String url) {
HttpGet request = new HttpGet(url); HttpGet request = new HttpGet(url);
request.setHeader(new BasicHeader(HttpHeaders.ACCEPT, "application/vnd.initializr.v2+json")); request.setHeader(new BasicHeader(HttpHeaders.ACCEPT,
"application/vnd.initializr.v2+json"));
return execute(request, url, "retrieve metadata"); return execute(request, url, "retrieve metadata");
} }
......
...@@ -138,7 +138,8 @@ class InitializrServiceMetadata { ...@@ -138,7 +138,8 @@ class InitializrServiceMetadata {
} }
JSONObject type = root.getJSONObject(TYPE_EL); JSONObject type = root.getJSONObject(TYPE_EL);
JSONArray array = type.getJSONArray(VALUES_EL); JSONArray array = type.getJSONArray(VALUES_EL);
String defaultType = type.has(DEFAULT_ATTRIBUTE) ? type.getString(DEFAULT_ATTRIBUTE) : null; String defaultType = type.has(DEFAULT_ATTRIBUTE) ? type
.getString(DEFAULT_ATTRIBUTE) : null;
for (int i = 0; i < array.length(); i++) { for (int i = 0; i < array.length(); i++) {
JSONObject typeJson = array.getJSONObject(i); JSONObject typeJson = array.getJSONObject(i);
ProjectType projectType = parseType(typeJson, defaultType); ProjectType projectType = parseType(typeJson, defaultType);
......
...@@ -25,7 +25,6 @@ import java.util.List; ...@@ -25,7 +25,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.http.client.utils.URIBuilder; import org.apache.http.client.utils.URIBuilder;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
...@@ -209,7 +208,8 @@ class ProjectGenerationRequest { ...@@ -209,7 +208,8 @@ class ProjectGenerationRequest {
} }
if (!this.dependencies.isEmpty()) { if (!this.dependencies.isEmpty()) {
builder.setParameter("dependencies", StringUtils.collectionToCommaDelimitedString(this.dependencies)); builder.setParameter("dependencies",
StringUtils.collectionToCommaDelimitedString(this.dependencies));
} }
if (this.javaVersion != null) { if (this.javaVersion != null) {
builder.setParameter("javaVersion", this.javaVersion); builder.setParameter("javaVersion", this.javaVersion);
......
...@@ -43,7 +43,8 @@ public class InitializrServiceMetadataTests { ...@@ -43,7 +43,8 @@ public class InitializrServiceMetadataTests {
assertEquals("1.7", metadata.getDefaults().get("javaVersion")); assertEquals("1.7", metadata.getDefaults().get("javaVersion"));
assertEquals("org.test", metadata.getDefaults().get("groupId")); assertEquals("org.test", metadata.getDefaults().get("groupId"));
assertEquals("demo", metadata.getDefaults().get("name")); assertEquals("demo", metadata.getDefaults().get("name"));
assertEquals("Demo project for Spring Boot", metadata.getDefaults().get("description")); assertEquals("Demo project for Spring Boot",
metadata.getDefaults().get("description"));
assertEquals("jar", metadata.getDefaults().get("packaging")); assertEquals("jar", metadata.getDefaults().get("packaging"));
assertEquals("java", metadata.getDefaults().get("language")); assertEquals("java", metadata.getDefaults().get("language"));
assertEquals("demo", metadata.getDefaults().get("artifactId")); assertEquals("demo", metadata.getDefaults().get("artifactId"));
......
...@@ -108,7 +108,8 @@ public class ProjectGenerationRequestTests { ...@@ -108,7 +108,8 @@ public class ProjectGenerationRequestTests {
this.request.setType("custom"); this.request.setType("custom");
this.request.getDependencies().add("data-rest"); this.request.getDependencies().add("data-rest");
assertEquals(new URI(ProjectGenerationRequest.DEFAULT_SERVICE_URL assertEquals(new URI(ProjectGenerationRequest.DEFAULT_SERVICE_URL
+ "/foo?dependencies=data-rest&type=custom"), this.request.generateUrl(metadata)); + "/foo?dependencies=data-rest&type=custom"),
this.request.generateUrl(metadata));
} }
@Test @Test
......
{ {
"_links": { "_links": {
"maven-build": { "maven-build": {
"href": "http://localhost:8080/pom.xml?{dependencies,type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}", "href": "http://localhost:8080/pom.xml?{dependencies,type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
"templated": true "templated": true
}, },
"maven-project": { "maven-project": {
"href": "http://localhost:8080/starter.zip{?dependencies,type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}", "href": "http://localhost:8080/starter.zip{?dependencies,type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
"templated": true "templated": true
}, },
"gradle-build": { "gradle-build": {
"href": "http://localhost:8080/build.gradle{?dependencies,type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}", "href": "http://localhost:8080/build.gradle{?dependencies,type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
"templated": true "templated": true
}, },
"gradle-project": { "gradle-project": {
"href": "http://localhost:8080/starter.zip{?dependencies,type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}", "href": "http://localhost:8080/starter.zip{?dependencies,type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
"templated": true "templated": true
} }
}, },
"dependencies": { "dependencies": {
"type": "hierarchical-multi-select", "type": "hierarchical-multi-select",
"values": [ "values": [
{ {
"name": "Core", "name": "Core",
"values": [ "values": [
{ {
"name": "Security", "name": "Security",
"id": "security", "id": "security",
"description": "Security description" "description": "Security description"
}, },
{ {
"name": "AOP", "name": "AOP",
"id": "aop" "id": "aop"
} }
] ]
}, },
{ {
"name": "Data", "name": "Data",
"values": [ "values": [
{ {
"name": "JDBC", "name": "JDBC",
"id": "jdbc" "id": "jdbc"
}, },
{ {
"name": "JPA", "name": "JPA",
"id": "data-jpa" "id": "data-jpa"
}, },
{ {
"name": "MongoDB", "name": "MongoDB",
"id": "data-mongodb" "id": "data-mongodb"
} }
] ]
} }
] ]
}, },
"type": { "type": {
"type": "action", "type": "action",
"default": "maven-project", "default": "maven-project",
"values": [ "values": [
{ {
"id": "maven-build", "id": "maven-build",
"name": "Maven POM", "name": "Maven POM",
"action": "/pom.xml", "action": "/pom.xml",
"tags": { "tags": {
"build": "maven", "build": "maven",
"format": "build" "format": "build"
} }
}, },
{ {
"id": "maven-project", "id": "maven-project",
"name": "Maven Project", "name": "Maven Project",
"action": "/starter.zip", "action": "/starter.zip",
"tags": { "tags": {
"build": "maven", "build": "maven",
"format": "project" "format": "project"
} }
}, },
{ {
"id": "gradle-build", "id": "gradle-build",
"name": "Gradle Config", "name": "Gradle Config",
"action": "/build.gradle", "action": "/build.gradle",
"tags": { "tags": {
"build": "gradle", "build": "gradle",
"format": "build" "format": "build"
} }
}, },
{ {
"id": "gradle-project", "id": "gradle-project",
"name": "Gradle Project", "name": "Gradle Project",
"action": "/starter.zip", "action": "/starter.zip",
"tags": { "tags": {
"build": "gradle", "build": "gradle",
"format": "project" "format": "project"
} }
} }
] ]
}, },
"packaging": { "packaging": {
"type": "single-select", "type": "single-select",
"default": "jar", "default": "jar",
"values": [ "values": [
{ {
"id": "jar", "id": "jar",
"name": "Jar" "name": "Jar"
}, },
{ {
"id": "war", "id": "war",
"name": "War" "name": "War"
} }
] ]
}, },
"javaVersion": { "javaVersion": {
"type": "single-select", "type": "single-select",
"default": "1.7", "default": "1.7",
"values": [ "values": [
{ {
"id": "1.6", "id": "1.6",
"name": "1.6" "name": "1.6"
}, },
{ {
"id": "1.7", "id": "1.7",
"name": "1.7" "name": "1.7"
}, },
{ {
"id": "1.8", "id": "1.8",
"name": "1.8" "name": "1.8"
} }
] ]
}, },
"language": { "language": {
"type": "single-select", "type": "single-select",
"default": "java", "default": "java",
"values": [ "values": [
{ {
"id": "groovy", "id": "groovy",
"name": "Groovy" "name": "Groovy"
}, },
{ {
"id": "java", "id": "java",
"name": "Java" "name": "Java"
} }
] ]
}, },
"bootVersion": { "bootVersion": {
"type": "single-select", "type": "single-select",
"default": "1.1.8.RELEASE", "default": "1.1.8.RELEASE",
"values": [ "values": [
{ {
"id": "1.2.0.BUILD-SNAPSHOT", "id": "1.2.0.BUILD-SNAPSHOT",
"name": "1.2.0 (SNAPSHOT)" "name": "1.2.0 (SNAPSHOT)"
}, },
{ {
"id": "1.1.8.RELEASE", "id": "1.1.8.RELEASE",
"name": "1.1.8" "name": "1.1.8"
}, },
{ {
"id": "1.1.8.BUILD-SNAPSHOT", "id": "1.1.8.BUILD-SNAPSHOT",
"name": "1.1.8 (SNAPSHOT)" "name": "1.1.8 (SNAPSHOT)"
}, },
{ {
"id": "1.0.2.RELEASE", "id": "1.0.2.RELEASE",
"name": "1.0.2" "name": "1.0.2"
} }
] ]
}, },
"groupId": { "groupId": {
"type": "text", "type": "text",
"default": "org.test" "default": "org.test"
}, },
"artifactId": { "artifactId": {
"type": "text", "type": "text",
"default": "demo" "default": "demo"
}, },
"version": { "version": {
"type": "text", "type": "text",
"default": "0.0.1-SNAPSHOT" "default": "0.0.1-SNAPSHOT"
}, },
"name": { "name": {
"type": "text", "type": "text",
"default": "demo" "default": "demo"
}, },
"description": { "description": {
"type": "text", "type": "text",
"default": "Demo project for Spring Boot" "default": "Demo project for Spring Boot"
}, },
"packageName": { "packageName": {
"type": "text", "type": "text",
"default": "demo" "default": "demo"
} }
} }
\ No newline at end of file
{ {
"_links": { "_links": {
"maven-build": { "maven-build": {
"href": "http://localhost:8080/pom.xml?style={dependencies}{&type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}", "href": "http://localhost:8080/pom.xml?style={dependencies}{&type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
"templated": true "templated": true
}, },
"maven-project": { "maven-project": {
"href": "http://localhost:8080/starter.zip?style={dependencies}{&type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}", "href": "http://localhost:8080/starter.zip?style={dependencies}{&type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
"templated": true "templated": true
}, },
"gradle-build": { "gradle-build": {
"href": "http://localhost:8080/build.gradle?style={dependencies}{&type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}", "href": "http://localhost:8080/build.gradle?style={dependencies}{&type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
"templated": true "templated": true
}, },
"gradle-project": { "gradle-project": {
"href": "http://localhost:8080/starter.zip?style={dependencies}{&type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}", "href": "http://localhost:8080/starter.zip?style={dependencies}{&type,packaging,javaVersion,language,bootVersion,groupId,artifactId,version,name,description,packageName}",
"templated": true "templated": true
} }
}, },
"dependencies": { "dependencies": {
"type": "hierarchical-multi-select", "type": "hierarchical-multi-select",
"values": [ "values": [
{ {
"name": "Core", "name": "Core",
"values": [ "values": [
{ {
"name": "Security", "name": "Security",
"id": "security", "id": "security",
"description": "Security description" "description": "Security description"
}, },
{ {
"name": "AOP", "name": "AOP",
"id": "aop" "id": "aop"
} }
] ]
}, },
{ {
"name": "Data", "name": "Data",
"values": [ "values": [
{ {
"name": "JDBC", "name": "JDBC",
"id": "jdbc" "id": "jdbc"
}, },
{ {
"name": "JPA", "name": "JPA",
"id": "data-jpa" "id": "data-jpa"
}, },
{ {
"name": "MongoDB", "name": "MongoDB",
"id": "data-mongodb" "id": "data-mongodb"
} }
] ]
} }
] ]
}, },
"type": { "type": {
"type": "action", "type": "action",
"values": [ "values": [
{ {
"id": "maven-build", "id": "maven-build",
"name": "Maven POM", "name": "Maven POM",
"action": "/pom.xml", "action": "/pom.xml",
"tags": { "tags": {
"build": "maven", "build": "maven",
"format": "build" "format": "build"
} }
}, },
{ {
"id": "maven-project", "id": "maven-project",
"name": "Maven Project", "name": "Maven Project",
"action": "/starter.zip", "action": "/starter.zip",
"tags": { "tags": {
"build": "maven", "build": "maven",
"format": "project" "format": "project"
} }
}, },
{ {
"id": "maven-project-2", "id": "maven-project-2",
"name": "Another Maven Project", "name": "Another Maven Project",
"action": "/starter.zip", "action": "/starter.zip",
"tags": { "tags": {
"build": "maven", "build": "maven",
"format": "project" "format": "project"
} }
}, },
{ {
"id": "gradle-build", "id": "gradle-build",
"name": "Gradle Config", "name": "Gradle Config",
"action": "/build.gradle", "action": "/build.gradle",
"tags": { "tags": {
"build": "gradle", "build": "gradle",
"format": "build" "format": "build"
} }
}, },
{ {
"id": "gradle-project", "id": "gradle-project",
"name": "Gradle Project", "name": "Gradle Project",
"action": "/starter.zip", "action": "/starter.zip",
"tags": { "tags": {
"build": "gradle", "build": "gradle",
"format": "project" "format": "project"
} }
}, },
{ {
"id": "gradle-project-2", "id": "gradle-project-2",
"name": "Another Gradle Project", "name": "Another Gradle Project",
"action": "/starter.zip", "action": "/starter.zip",
"tags": { "tags": {
"build": "gradle", "build": "gradle",
"format": "project" "format": "project"
} }
} }
] ]
}, },
"packaging": { "packaging": {
"type": "single-select", "type": "single-select",
"default": "jar", "default": "jar",
"values": [ "values": [
{ {
"id": "jar", "id": "jar",
"name": "Jar" "name": "Jar"
}, },
{ {
"id": "war", "id": "war",
"name": "War" "name": "War"
} }
] ]
}, },
"javaVersion": { "javaVersion": {
"type": "single-select", "type": "single-select",
"default": "1.7", "default": "1.7",
"values": [ "values": [
{ {
"id": "1.6", "id": "1.6",
"name": "1.6" "name": "1.6"
}, },
{ {
"id": "1.7", "id": "1.7",
"name": "1.7" "name": "1.7"
}, },
{ {
"id": "1.8", "id": "1.8",
"name": "1.8" "name": "1.8"
} }
] ]
}, },
"language": { "language": {
"type": "single-select", "type": "single-select",
"default": "java", "default": "java",
"values": [ "values": [
{ {
"id": "groovy", "id": "groovy",
"name": "Groovy" "name": "Groovy"
}, },
{ {
"id": "java", "id": "java",
"name": "Java" "name": "Java"
} }
] ]
}, },
"bootVersion": { "bootVersion": {
"type": "single-select", "type": "single-select",
"default": "1.1.8.RELEASE", "default": "1.1.8.RELEASE",
"values": [ "values": [
{ {
"id": "1.2.0.BUILD-SNAPSHOT", "id": "1.2.0.BUILD-SNAPSHOT",
"name": "1.2.0 (SNAPSHOT)" "name": "1.2.0 (SNAPSHOT)"
}, },
{ {
"id": "1.1.8.RELEASE", "id": "1.1.8.RELEASE",
"name": "1.1.8" "name": "1.1.8"
}, },
{ {
"id": "1.1.8.BUILD-SNAPSHOT", "id": "1.1.8.BUILD-SNAPSHOT",
"name": "1.1.8 (SNAPSHOT)" "name": "1.1.8 (SNAPSHOT)"
}, },
{ {
"id": "1.0.2.RELEASE", "id": "1.0.2.RELEASE",
"name": "1.0.2" "name": "1.0.2"
} }
] ]
}, },
"groupId": { "groupId": {
"type": "text", "type": "text",
"default": "org.test" "default": "org.test"
}, },
"artifactId": { "artifactId": {
"type": "text", "type": "text",
"default": "demo" "default": "demo"
}, },
"version": { "version": {
"type": "text", "type": "text",
"default": "0.0.1-SNAPSHOT" "default": "0.0.1-SNAPSHOT"
}, },
"name": { "name": {
"type": "text", "type": "text",
"default": "demo" "default": "demo"
}, },
"description": { "description": {
"type": "text", "type": "text",
"default": "Demo project for Spring Boot" "default": "Demo project for Spring Boot"
}, },
"packageName": { "packageName": {
"type": "text", "type": "text",
"default": "demo" "default": "demo"
} }
} }
\ No newline at end of file
...@@ -157,6 +157,11 @@ content into your application; rather pick only the properties that you need. ...@@ -157,6 +157,11 @@ content into your application; rather pick only the properties that you need.
spring.velocity.suffix=.vm spring.velocity.suffix=.vm
spring.velocity.view-names= # whitelist of view names that can be resolved spring.velocity.view-names= # whitelist of view names that can be resolved
# JERSEY ({sc-spring-boot-autoconfigure}}/jersey/JerseyProperties.{sc-ext}[JerseyProperties])
spring.jersey.type=servlet # servlet or filter
spring.jersey.init= # init params
spring.jersey.filter.order=
# INTERNATIONALIZATION ({sc-spring-boot-autoconfigure}/MessageSourceAutoConfiguration.{sc-ext}[MessageSourceAutoConfiguration]) # INTERNATIONALIZATION ({sc-spring-boot-autoconfigure}/MessageSourceAutoConfiguration.{sc-ext}[MessageSourceAutoConfiguration])
spring.messages.basename=messages spring.messages.basename=messages
spring.messages.cacheSeconds=-1 spring.messages.cacheSeconds=-1
......
...@@ -1084,14 +1084,12 @@ servlet will be registered and mapped to '`+/*+`' by default. You can change the ...@@ -1084,14 +1084,12 @@ servlet will be registered and mapped to '`+/*+`' by default. You can change the
by adding `@ApplicationPath` to your `ResourceConfig`. by adding `@ApplicationPath` to your `ResourceConfig`.
By default Jersey will be set up as a Servlet in a `@Bean` of type By default Jersey will be set up as a Servlet in a `@Bean` of type
`ServletRegistrationBean` named "jerseyServletRegistration". You can `ServletRegistrationBean` named "jerseyServletRegistration". You can disable or override
disable or override that bean by creating one of your own with the that bean by creating one of your own with the same name. You can also use a Filter
same name. You can also use a Filter instead of a Servlet by setting instead of a Servlet by setting `spring.jersey.type=filter` (in which case the `@Bean` to
`spring.jersey.type=filter` (in which case the `@Bean` to replace or replace or override is "jerseyFilterRegistration"). The servlet has an `@Order`which you
override is "jerseyFilterRegistration"). The servlet has an `@Order` can set with `spring.jersey.filter.order`. Both the Servlet and the Filter registrations
which you can set with `spring.jersey.filter.order`. Both the Servlet can be given init parameters using `spring.jersey.init.*` to specify a map of properties.
and the Filter registrations can be given init parameters using
`spring.jersey.init.*` to specify a map of properties.
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].
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment