Spring Boot (1.2.7) web app (responds to SSL requests) works great running from Intellij IDEA.
Build JAR artifact to run from command line, throws error upon start
org.springframework.context.ApplicationContextException:
Unable to start embedded container;
nested exception is
org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
Questions
- How can I avoid this error?
- If I need to declare an EmbeddedServletContainerFactory, how can I have its ServletContainer handle requests for my Controller?
Solutions Tried
Added EmbeddedservletContainerFactory as requested by error. Project now starts from JAR, but requests are not being received by Controller like it does when running from IntelliJ.
Here's what my Application.class looks like after adding the EmbeddedServletContainerFactory
package org.coursera.diabetes;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.support.ConnectionSource;
import diabetes.common.model.*;
import org.apache.catalina.connector.Connector;
import org.apache.coyote.http11.Http11NioProtocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
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.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
@SpringBootApplication
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
private static final String dbUrl = "jdbc:h2:mem:testdb";
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
@Profile("production")
public EmbeddedServletContainerFactory servletContainer(@Value("${keystore.file}") Resource keystoreFile) {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
//factory.setPort(8443);
String absoluteKeystoreFile = "";
try {
absoluteKeystoreFile = keystoreFile.getFile().getAbsolutePath();
logger.info(String.format("******** keystore: %s", absoluteKeystoreFile));
} catch (IOException e) {
e.printStackTrace();
}
tomcat.addAdditionalTomcatConnectors(createSslConnector(absoluteKeystoreFile));
return tomcat;
}
private Connector createSslConnector(String absKeystoreFile) {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
try {
connector.setScheme("https");
connector.setSecure(true);
connector.setPort(8443);
protocol.setSSLEnabled(true);
protocol.setKeystoreFile(absKeystoreFile);
protocol.setKeystorePass("changeit");
protocol.setKeyAlias("tomcat");
return connector;
}
catch (Exception ex) {
throw new IllegalStateException("can't access keystore: [" + "keystore"
+ "] or truststore: [" + "keystore" + "]", ex);
}
}
}
Notes
Spring Boot (web) application works great running from Intellij IDEA, responding to https requests without needing to do anything more than a few additional lines in application.properties:
security.require-ssl=true
server.port=8443
server.ssl.key-store=src/main/resources/private/keystore
server.ssl.key-store-password=changeit
server.ssl.key-password=changeit
To start JAR artifact from command line I use:
java -Dspring.profiles.active=production -Dkeystore.file=file:///$PWD/keystore -jar diabetes-spring.jar
JAR starts without error doing this, but https web requests (which work from Intellij) simply return Apache/tomcat 404 "The requested resource is not available".
EDITS
Running the JAR with -Ddebug outputs the following information (I'm omitting all the DEBUG messages for not finding config files application.properties / application / application-production.properties which don't seem pertitenent)
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot ::
2015-11-13 14:16:39.980 INFO 47600 --- [ main] org.coursera.diabetes.Applica
tion : Starting Application on Bakers-MacBook-Pro.local with PID 47600 (/User
s/baker/coursera-android/MoCCA-15/spring-tests/diabetes_root2/diabetes-spring/out/artifa
cts/diabetes_spring_jar/diabetes-spring.jar started by blam in /Users/blam/coursera-and
roid/MoCCA-15/spring-tests/diabetes_root2/diabetes-spring/out/artifacts/diabetes_spring
_jar)
2015-11-13 14:16:39.983 DEBUG 47600 --- [ main] o.s.boot.SpringApplication
: Loading source class org.coursera.diabetes.Application
2015-11-13 14:16:40.011 DEBUG 47600 --- [ main] o.s.b.c.c.ConfigFileApplicati
onListener : Activated profiles production
2015-11-13 14:16:40.011 DEBUG 47600 --- [ main] o.s.b.c.c.ConfigFileApplicati
onListener : Loaded config file 'file:./config/application.properties'
2015-11-13 14:16:40.020 INFO 47600 --- [ main] ationConfigEmbeddedWebApplica
tionContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbe
ddedWebApplicationContext@23faf8f2: startup date [Fri Nov 13 14:16:40 WET 2015]; root o
f context hierarchy
2015-11-13 14:16:40.022 DEBUG 47600 --- [ main] ationConfigEmbeddedWebApplica
tionContext : Bean factory for org.springframework.boot.context.embedded.AnnotationConf
igEmbeddedWebApplicationContext@23faf8f2: org.springframework.beans.factory.support.Def
aultListableBeanFactory@6cc7b4de: defining beans [org.springframework.context.annotatio
n.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.inter
nalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequired
AnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProc
essor,application]; root of factory hierarchy
2015-11-13 14:16:40.220 DEBUG 47600 --- [ main] ationConfigEmbeddedWebApplica
tionContext : Unable to locate MessageSource with name 'messageSource': using default [
org.springframework.context.support.DelegatingMessageSource@20ce78ec]
2015-11-13 14:16:40.221 DEBUG 47600 --- [ main] ationConfigEmbeddedWebApplica
tionContext : Using ApplicationEventMulticaster [org.springframework.context.event.Simp
leApplicationEventMulticaster@393671df]
2015-11-13 14:16:40.226 WARN 47600 --- [ main] ationConfigEmbeddedWebApplica
tionContext : Exception encountered during context initialization - cancelling refresh
attempt
org.springframework.context.ApplicationContextException: Unable to start embedded conta
iner; nested exception is org.springframework.context.ApplicationContextException: Unab
le to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactor
y bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRe
fresh(EmbeddedWebApplicationContext.java:132)
at org.springframework.context.support.AbstractApplicationContext.refresh(Abstr
actApplicationContext.java:474)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refr
esh(EmbeddedWebApplicationContext.java:117)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:68
9)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:969)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:958)
at org.coursera.diabetes.Application.main(Application.java:40)
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:182)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:155)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:129)
... 7 common frames omitted
2015-11-13 14:16:40.227 INFO 47600 --- [ main] .b.l.ClasspathLoggingApplicationListener : Application failed to start with classpath: [file:/Users/baker/coursera-android/MoCCA-15/spring-tests/diabetes_root2/diabetes-spring/out/artifacts/diabetes_spring_jar/diabetes-spring.jar]
2015-11-13 14:16:40.228 ERROR 47600 --- [ main] o.s.boot.SpringApplication : Application startup failed
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:132)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:117)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:689)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:969)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:958)
at org.coursera.diabetes.Application.main(Application.java:40)
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:182)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:155)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:129)
... 7 common frames omitted