I am trying to deploy a Spring Boot application to Glassfish 3.x but I can't get it to work. If I run the project via mvn spring-boot:run
or I deploy the war on a Tomcat 7, it works, but if I deploy it on a Glassfish 3.1.2.2 the deploy fails before it even gets to spring boots initialization.
[#|2014-08-04T11:38:36.668+0200|WARNING|glassfish3.1.2|global|_ThreadID=50;_ThreadName=Thread-2;|Error in annotation processing: java.lang.NoClassDefFoundError: org/springframework/batch/core/configuration/annotation/BatchConfigurer|#]
[#|2014-08-04T11:38:36.677+0200|SEVERE|glassfish3.1.2|global|_ThreadID=50;_ThreadName=Thread-2;|Class [ org/flywaydb/core/Flyway ] not found. Error while loading [ class org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration$FlywayConfiguration ]|#]
[#|2014-08-04T11:38:36.700+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.core.com.sun.enterprise.v3.server|_ThreadID=50;_ThreadName=Thread-2;|Exception while deploying the app [spring]|#]
[#|2014-08-04T11:38:36.700+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.core.com.sun.enterprise.v3.server|_ThreadID=50;_ThreadName=Thread-2;|sun.reflect.annotation.TypeNotPresentExceptionProxy
java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy
at sun.reflect.annotation.AnnotationParser.parseClassArray(AnnotationParser.java:673)
at sun.reflect.annotation.AnnotationParser.parseArray(AnnotationParser.java:480)
at sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:306)
at sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:241)
at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:88)
at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:70)
at java.lang.Class.initAnnotationsIfNecessary(Class.java:3217)
at java.lang.Class.getAnnotations(Class.java:3197)
at org.glassfish.apf.impl.AnnotationProcessorImpl.processAnnotations(AnnotationProcessorImpl.java:285)
at org.glassfish.apf.impl.AnnotationProcessorImpl.process(AnnotationProcessorImpl.java:195)
at org.glassfish.apf.impl.AnnotationProcessorImpl.process(AnnotationProcessorImpl.java:134)
at com.sun.enterprise.deployment.archivist.Archivist.processAnnotations(Archivist.java:598)
at com.sun.enterprise.deployment.archivist.Archivist.readAnnotations(Archivist.java:456)
at com.sun.enterprise.deployment.archivist.Archivist.readAnnotations(Archivist.java:429)
at com.sun.enterprise.deployment.archivist.Archivist.readRestDeploymentDescriptors(Archivist.java:405)
at com.sun.enterprise.deployment.archivist.Archivist.readDeploymentDescriptors(Archivist.java:380)
at com.sun.enterprise.deployment.archivist.Archivist.open(Archivist.java:243)
at com.sun.enterprise.deployment.archivist.Archivist.open(Archivist.java:252)
at com.sun.enterprise.deployment.archivist.Archivist.open(Archivist.java:213)
at com.sun.enterprise.deployment.archivist.ApplicationFactory.openArchive(ApplicationFactory.java:165)
at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:185)
at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:94)
at com.sun.enterprise.v3.server.ApplicationLifecycle.loadDeployer(ApplicationLifecycle.java:827)
at com.sun.enterprise.v3.server.ApplicationLifecycle.setupContainerInfos(ApplicationLifecycle.java:769)
at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:368)
at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:240)
at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:389)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$1.execute(CommandRunnerImpl.java:353)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:363)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1085)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1200(CommandRunnerImpl.java:95)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1291)
at org.glassfish.deployment.autodeploy.AutoOperation.run(AutoOperation.java:145)
at org.glassfish.deployment.autodeploy.AutoDeployer.deploy(AutoDeployer.java:575)
at org.glassfish.deployment.autodeploy.AutoDeployer.deployAll(AutoDeployer.java:461)
at org.glassfish.deployment.autodeploy.AutoDeployer.run(AutoDeployer.java:389)
at org.glassfish.deployment.autodeploy.AutoDeployer.run(AutoDeployer.java:380)
at org.glassfish.deployment.autodeploy.AutoDeployService$1.run(AutoDeployService.java:220)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
Disclaimer: I am using a Controller which extends an AbstractController
, because we have this structure in another web application, and the next step is to migrate it to Spring Boot.
My configuration so far:
SampleController.java
@Controller("myController")
public class SampleController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
response.getWriter().print("Hello world!");
return null;
}
}
Application.java
@EnableAutoConfiguration
@Configuration
@ComponentScan
public class Application extends SpringBootServletInitializer {
@Autowired
ApplicationContext applicationContext;
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
@Bean
public SimpleUrlHandlerMapping sampleServletMapping() {
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
SampleController sampleController = (SampleController) applicationContext.getBean("myController");
mapping.setUrlMap(Collections.singletonMap("index", sampleController));
mapping.setOrder(0);
return mapping;
}
}
You've hit a limitation in GlassFish 3.x and I don't think it's possible to get this to work.
The problem you're seeing is caused by GlassFish scanning your application for annotations. It does this by loading all of the classes in the application and it's failing as a class that's referenced by one of the annotations isn't on the classpath. Unfortunately, there's no way in GlassFish 3 to configure what it does and does not scan for annotations. I believe that things have improved in GlassFish 4 so, if upgrading is an option, you might want to try that.