package com.github.signed.sandboxes.spring.boot; import java.util.Optional; import org.junit.rules.ExternalResource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; import retrofit.RestAdapter; public class SpringApplicationRule extends ExternalResource { private final SpringApplicationBuilder springApplicationBuilder = new SpringApplicationBuilder() .showBanner(false) .sources(BootApplication.class, ChooseAnAvailablePort.class); private final RuleConfiguration ruleConfiguration = new RuleConfiguration(); private Optional<ConfigurableApplicationContext> context = Optional.empty(); public <T> T client(Class<T> type) { ensureServerIsStarted(); RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint(baseUri()) .build(); return restAdapter.create(type); } public String baseUri() { return "http://localhost:" + ruleConfiguration.port(); } @Override protected void after() { if (context.isPresent()) { SpringApplication.exit(context.get()); } } private void ensureServerIsStarted() { if (context.isPresent()) { return; } SpringApplication springApplication = springApplicationBuilder.build(); ConfigurableApplicationContext configurableContext = springApplication.run(); ConfigurableListableBeanFactory beanFactory = configurableContext.getBeanFactory(); beanFactory.initializeBean(ruleConfiguration, "ruleConfiguration"); beanFactory.autowireBean(ruleConfiguration); context = Optional.of(configurableContext); } @Component public static class RuleConfiguration { public EmbeddedWebApplicationContext server; @Autowired public void set(EmbeddedWebApplicationContext server) { this.server = server; } public int port() { return server.getEmbeddedServletContainer().getPort(); } // @Value("${local.server.port}") // public int port; } @Configuration public static class ChooseAnAvailablePort implements EmbeddedServletContainerCustomizer { @Override public void customize(ConfigurableEmbeddedServletContainer container) { container.setPort(0); } } }