Commit 36a5c96a by Johannes Edmeier

Update to boot 1.3.0.M2

remove logfileEndpoint rename logback.xml to logback-spring.xml in samples fixes #98
parent 3f4da621
......@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.0.M1</version>
<version>1.3.0.M2</version>
</parent>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin</artifactId>
......@@ -18,7 +18,7 @@
<java.version>1.7</java.version>
<main.basedir>${basedir}</main.basedir>
<passphrase>${gpg.passphrase}</passphrase>
<spring-boot.version>1.3.0.M1</spring-boot.version>
<spring-boot.version>1.3.0.M2</spring-boot.version>
<spring-cloud.version>Angel.SR3</spring-cloud.version>
<build-plugin.jacoco.version>0.7.5.201505241946</build-plugin.jacoco.version>
<build-plugin.coveralls.version>3.0.1</build-plugin.coveralls.version>
......
......@@ -30,7 +30,7 @@ module.exports = function ($resource, $http) {
application.capabilities = {};
if (application.managementUrl) {
$http.get('api/applications/' + application.id + '/configprops').success(function(configprops) {
application.capabilities.logfile = isEndpointPresent('logfileEndpoint', configprops);
application.capabilities.logfile = isEndpointPresent('logfileMvcEndpoint', configprops);
application.capabilities.activiti = isEndpointPresent('processEngineEndpoint', configprops);
application.capabilities.restart = isEndpointPresent('restartEndpoint', configprops);
application.capabilities.refresh = isEndpointPresent('refreshEndpoint', configprops);
......
......@@ -61,6 +61,13 @@
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
<optional>true</optional>
<!-- https://github.com/spring-projects/spring-boot/issues/3418 -->
<exclusions>
<exclusion>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
......
......@@ -15,16 +15,13 @@
*/
package de.codecentric.boot.admin.config;
import javax.activation.MimeType;
import javax.mail.internet.MimeMessage;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.MailSender;
......@@ -32,18 +29,19 @@ import org.springframework.mail.MailSender;
import de.codecentric.boot.admin.notify.MailNotifier;
@Configuration
@ConditionalOnClass({ MimeMessage.class, MimeType.class })
@ConditionalOnProperty(prefix = "spring.mail", value = "host")
@ConditionalOnMissingBean(MailSender.class)
@EnableConfigurationProperties(MailProperties.class)
public class MailNotifierConfiguration extends MailSenderAutoConfiguration {
@ConditionalOnBean(MailSender.class)
@AutoConfigureAfter({ MailSenderAutoConfiguration.class })
public class MailNotifierConfiguration {
@Autowired
private MailSender mailSender;
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.boot.admin.notify", name = "enabled", matchIfMissing = true)
@ConfigurationProperties("spring.boot.admin.notify")
public MailNotifier mailNotifier() {
return new MailNotifier(mailSender());
return new MailNotifier(mailSender);
}
}
\ No newline at end of file
......@@ -12,6 +12,7 @@ import java.util.List;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration;
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.cloud.client.discovery.noop.NoopDiscoveryClientAutoConfiguration;
......@@ -97,6 +98,7 @@ public class AdminServerWebConfigurationTest {
applicationContext.register(PropertyPlaceholderAutoConfiguration.class);
applicationContext.register(ServerPropertiesAutoConfiguration.class);
applicationContext.register(NoopDiscoveryClientAutoConfiguration.class);
applicationContext.register(MailSenderAutoConfiguration.class);
applicationContext.register(AdminServerWebConfiguration.class);
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
......
/*
* Copyright 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 de.codecentric.boot.admin.actuate;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* Controller that provides an API for logfiles, i.e. downloading the main logfile configured in
* environment property 'logging.file' that is standard, but optional property for spring-boot
* applications.
*/
@ConfigurationProperties(prefix = "endpoints.logfile")
public class LogfileMvcEndpoint implements MvcEndpoint {
private static final Logger LOGGER = LoggerFactory.getLogger(LogfileMvcEndpoint.class);
/**
* Logfile to serve at this endpoint. Defaults to ${logging.file}.
*/
@Value("${logging.file}")
private String logfile;
/**
* Path of the logfile-endpoint
*/
private String path = "/logfile";
/**
* Is the logfile endpoint sensitive
*/
private boolean sensitive = true;
/**
* Enable the logfile endpoint
*/
private boolean enabled = true;
@Override
public boolean isSensitive() {
return sensitive;
}
@Override
public String getPath() {
return path;
}
@Override
@SuppressWarnings("rawtypes")
public Class<? extends Endpoint> getEndpointType() {
return null;
}
public void setLogfile(String logfile) {
this.logfile = logfile;
}
public String getLogfile() {
return logfile;
}
public void setPath(String path) {
this.path = path;
}
public void setSensitive(boolean sensitive) {
this.sensitive = sensitive;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isEnabled() {
return enabled;
}
@RequestMapping(method = RequestMethod.GET)
public void invoke(HttpServletResponse response) throws IOException {
if (!isAvailable()) {
response.setStatus(HttpStatus.NOT_FOUND.value());
return;
}
Resource file = new FileSystemResource(logfile);
response.setContentType(MediaType.TEXT_PLAIN_VALUE);
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getFilename()
+ "\"");
FileCopyUtils.copy(file.getInputStream(), response.getOutputStream());
}
@RequestMapping(method = RequestMethod.HEAD)
@ResponseBody
public ResponseEntity<Object> available() {
if (isAvailable()) {
return new ResponseEntity<>(HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
private boolean isAvailable() {
if (!enabled) {
return false;
}
if (logfile == null) {
LOGGER.error("Logfile download failed for missing property 'logging.file'");
return false;
}
Resource file = new FileSystemResource(logfile);
if (!file.exists()) {
LOGGER.error("Logfile download failed for missing file at path={}", logfile);
return false;
}
return true;
}
}
......@@ -18,7 +18,6 @@ package de.codecentric.boot.admin.config;
import java.util.Arrays;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
......@@ -29,7 +28,6 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConvert
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.web.client.RestTemplate;
import de.codecentric.boot.admin.actuate.LogfileMvcEndpoint;
import de.codecentric.boot.admin.services.ApplicationRegistrator;
import de.codecentric.boot.admin.services.RegistrationApplicationListener;
import de.codecentric.boot.admin.web.BasicAuthHttpRequestInterceptor;
......@@ -40,84 +38,65 @@ import de.codecentric.boot.admin.web.BasicAuthHttpRequestInterceptor;
* itself.
*/
@Configuration
@EnableConfigurationProperties({ AdminProperties.class, AdminClientProperties.class })
@ConditionalOnProperty("spring.boot.admin.url")
public class SpringBootAdminClientAutoConfiguration {
@ConditionalOnProperty("spring.boot.admin.url")
@EnableConfigurationProperties({ AdminProperties.class, AdminClientProperties.class })
public static class AdminClientRegistrationConfig {
@Autowired
private AdminClientProperties client;
@Autowired
private AdminClientProperties client;
@Autowired
private AdminProperties admin;
@Autowired
private AdminProperties admin;
/**
* Task that registers the application at the spring-boot-admin application.
*/
@Bean
@ConditionalOnMissingBean
public ApplicationRegistrator registrator() {
return new ApplicationRegistrator(createRestTemplate(admin), admin, client);
}
/**
* Task that registers the application at the spring-boot-admin application.
*/
@Bean
@ConditionalOnMissingBean
public ApplicationRegistrator registrator() {
return new ApplicationRegistrator(createRestTemplate(admin), admin, client);
}
protected RestTemplate createRestTemplate(AdminProperties admin) {
RestTemplate template = new RestTemplate();
template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
protected RestTemplate createRestTemplate(AdminProperties admin) {
RestTemplate template = new RestTemplate();
template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
if (admin.getUsername() != null) {
template.setInterceptors(Arrays.<ClientHttpRequestInterceptor> asList(
new BasicAuthHttpRequestInterceptor(admin.getUsername(),
admin.getPassword())));
}
return template;
if (admin.getUsername() != null) {
template.setInterceptors(Arrays.<ClientHttpRequestInterceptor> asList(
new BasicAuthHttpRequestInterceptor(admin.getUsername(), admin.getPassword())));
}
/**
* TaskRegistrar that triggers the RegistratorTask every ten seconds.
*/
@Bean
public ScheduledTaskRegistrar taskRegistrar() {
ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar();
Runnable registratorTask = new Runnable() {
@Override
public void run() {
if (client.isServerInitialized()) {
registrator().register();
}
}
};
registrar.addFixedRateTask(registratorTask, admin.getPeriod());
return registrar;
}
return template;
}
/**
* ApplicationListener triggering registration after refresh/shutdown
*/
@Bean
public RegistrationApplicationListener registrationListener() {
RegistrationApplicationListener listener = new RegistrationApplicationListener(
registrator());
listener.setAutoDeregister(admin.isAutoDeregistration());
return listener;
}
/**
* TaskRegistrar that triggers the RegistratorTask every ten seconds.
*/
@Bean
public ScheduledTaskRegistrar taskRegistrar() {
ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar();
Runnable registratorTask = new Runnable() {
@Override
public void run() {
if (client.isServerInitialized()) {
registrator().register();
}
}
};
registrar.addFixedRateTask(registratorTask, admin.getPeriod());
return registrar;
}
@Configuration
@ConditionalOnExpression("${endpoints.logfile.enabled:true}")
@ConditionalOnProperty("logging.file")
public static class LogfileEndpointAutoConfiguration {
/**
* Exposes the logfile as acutator endpoint
*/
@Bean
public LogfileMvcEndpoint logfileEndpoint() {
return new LogfileMvcEndpoint();
}
/**
* ApplicationListener triggering registration after refresh/shutdown
*/
@Bean
public RegistrationApplicationListener registrationListener() {
RegistrationApplicationListener listener = new RegistrationApplicationListener(
registrator());
listener.setAutoDeregister(admin.isAutoDeregistration());
return listener;
}
}
/*
* Copyright 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 de.codecentric.boot.admin.actuate;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import org.junit.Test;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.util.FileCopyUtils;
public class LogfileMvcEndpointTest {
private LogfileMvcEndpoint controller = new LogfileMvcEndpoint();
@Test
public void logfile_noProperty() throws IOException {
assertEquals(HttpStatus.NOT_FOUND, controller.available().getStatusCode());
MockHttpServletResponse response = new MockHttpServletResponse();
controller.invoke(response);
assertEquals(HttpStatus.NOT_FOUND.value(), response.getStatus());
}
@Test
public void logfile_noFile() throws IOException {
controller.setLogfile("does_not_exist.log");
assertEquals(HttpStatus.NOT_FOUND, controller.available().getStatusCode());
MockHttpServletResponse response = new MockHttpServletResponse();
controller.invoke(response);
assertEquals(HttpStatus.NOT_FOUND.value(), response.getStatus());
}
@Test
public void logfile() throws IOException {
try {
FileCopyUtils.copy("--TEST--".getBytes(), new File("test.log"));
controller.setLogfile("test.log");
assertEquals(HttpStatus.OK, controller.available().getStatusCode());
MockHttpServletResponse response = new MockHttpServletResponse();
controller.invoke(response);
assertEquals(HttpStatus.OK.value(), response.getStatus());
assertEquals("--TEST--", response.getContentAsString());
} finally {
new File("test.log").delete();
}
}
}
......@@ -9,7 +9,6 @@ import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfigurat
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import de.codecentric.boot.admin.actuate.LogfileMvcEndpoint;
import de.codecentric.boot.admin.services.ApplicationRegistrator;
public class SpringBootAdminClientAutoConfigurationTest {
......@@ -27,35 +26,12 @@ public class SpringBootAdminClientAutoConfigurationTest {
public void not_active() {
load();
assertTrue(context.getBeansOfType(ApplicationRegistrator.class).isEmpty());
assertTrue(context.getBeansOfType(LogfileMvcEndpoint.class).isEmpty());
}
public void not_active_logfile() {
load();
assertTrue(context.getBeansOfType(ApplicationRegistrator.class).isEmpty());
context.getBean(LogfileMvcEndpoint.class);
}
@Test
public void active_nologfile() {
public void active() {
load("spring.boot.admin.url:http://localhost:8081");
context.getBean(ApplicationRegistrator.class);
assertTrue(context.getBeansOfType(LogfileMvcEndpoint.class).isEmpty());
}
@Test
public void active_logfile() {
load("spring.boot.admin.url:http://localhost:8081", "logging.file:spring.log");
context.getBean(LogfileMvcEndpoint.class);
context.getBean(ApplicationRegistrator.class);
}
@Test
public void active_logfile_supressed() {
load("spring.boot.admin.url:http://localhost:8081", "logging.file:spring.log",
"endpoints.logfile.enabled:false");
context.getBean(ApplicationRegistrator.class);
assertTrue(context.getBeansOfType(LogfileMvcEndpoint.class).isEmpty());
}
private void load(String... environment) {
......
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