4

Trying to setup a simple web application scheduler. So here is my configuration:

    <modelVersion>4.0.0</modelVersion>
    <groupId>org.springframework</groupId>
    <artifactId>scheduler</artifactId>
    <version>0.1.0</version>
    <packaging>war</packaging>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>1.1.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>1.1.7.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <version>1.1.7.RELEASE</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.enterprise</groupId>
            <artifactId>cdi-api</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>
    <properties>
        <start-class>hello.Application</start-class>
    </properties>
    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>hello.Application</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>spring-releases</id>
            <name>Spring Releases</name>
            <url>http://repo.spring.io/libs-release</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-releases</id>
            <name>Spring Releases</name>
            <url>http://repo.spring.io/libs-release</url>
        </pluginRepository>

    </pluginRepositories>
</project>

My classes look like below

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application implements WebApplicationInitializer {

    public static void main(String[] args) throws Exception {
SpringApplication.run(ScheduledTasks.class);
}
public void onStartup(ServletContext arg0) throws ServletException {

        SpringApplication.run(ScheduledTasks.class);

    }

    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
        factory.setPort(8081);
        factory.setSessionTimeout(50, TimeUnit.MINUTES);
        return factory;
    }
}
@EnableScheduling
public class ScheduledTasks {

    @Scheduled(fixedRate = 500)
    public void reportCurrentTime() {
        System.out.println("Testing successful ");
    }
}

But when i try to start the container i see the exception

ERROR 2592 --- [ost-startStop-1] o.s.boot.SpringApplication               : Application startup failed
...
...
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:174)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:147)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:121)
        ... 20 more

I tried to follow Spring Boot Testing: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean but in vain.

Kindly suggest, thanks

Community
  • 1
  • 1
Raghuveer
  • 2,859
  • 7
  • 34
  • 66

3 Answers3

7

You are only running ScheduledTasks:

SpringApplication.run(ScheduledTasks.class);

when you should run:

SpringApplication.run(Application.class);

Running ScheduledTasks means that Spring Boot doesn't know about the configuration in Application. Crucially, it means that it doesn't see @EnableAutoConfiguration which is what switches on auto-configuration and, because you have Tomcat on the classpath, creates the embedded Tomcat instance.

I would fix this by moving the @EnableScheduling annotation from ScheduledTasks to Application, running Application.class rather than ScheduledTasks.class, and annotating ScheduledTasks with @Component:

Application.class:

@Configuration
@EnableAutoConfiguration
@ComponentScan
@EnableScheduling
public class Application implements WebApplicationInitializer {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class);
    }

    // …
}

ScheduledTasks.class:

@Component
public class ScheduledTasks {

    @Scheduled(fixedRate = 500)
    public void reportCurrentTime() {
        System.out.println("Testing successful ");
    }
}

Moving @EnableScheduling means that its on a configuration class, where it belongs. Running Application.class means that Spring Boot sees all of its configuration, including enabling component scanning and enabling auto-configuration. Annotating ScheduledTasks with @Component means that it's found by component scanning and its @Scheduled method is detected.

This should get things up and running. I would also correct your pom so that you're not using a mixture of versions of Spring Boot (you have 1.1.6 and 1.1.7 in there at the moment) and get rid of your EmbeddedServletContainerFactory bean in favour of configuring the port and session timeout using application.properties in src/main/resources instead:

application.properties:

server.port = 8081
server.session-timeout = 3000
Naruto Sempai
  • 6,233
  • 8
  • 35
  • 51
Andy Wilkinson
  • 108,729
  • 24
  • 257
  • 242
  • I want this application to run from within a tomcat so how can i inject tomcat instance rather than a EmbeddedInstance. I did as you suggested but still i see the same exception. But atleast it is able to load the spring context now. – Raghuveer Dec 02 '14 at 12:00
  • If you're deploying your application to a standalone Tomcat instance then you'll need to configure the port in Tomcat's server.xml rather than via application.properties or your own EmbeddedServletContainerFactory bean. – Andy Wilkinson Dec 02 '14 at 15:45
  • yes i have configured my tomcat for 8080 and am able to access normal webapps on that port and am not using any properties files. The issue i see is since most of the applications on web talk about embedded container the web module configuration is not proper i think. As i previously said the webapp is trying to spring boot but failing because TomcatEmbeddedServletContainerFactory is missing. How can i let the webapp know that its available but not within it but its external to it. – Raghuveer Dec 03 '14 at 07:50
  • Also a strange thing is when tomcat starts i see spring-boot version as 1.1.9 where as i am using 1.1.7 – Raghuveer Dec 03 '14 at 07:58
  • You should extend SpringBootServletInitializer and override configure rather than implementing WebApplicationInitializer – Andy Wilkinson Dec 03 '14 at 08:15
  • "Whitelabel Error Page There was an unexpected error (type=Not Found, status=404). No message available" configure() is overridden to return application.sources(Application.class); and i see no other error message – Raghuveer Dec 03 '14 at 08:57
0

besides what @Andy Wilkinson pointed out which is true in the OP's case but not in mine

I saw that my spring-boot-starter-tomcat was with

<scope>provided</scope>

( as i was adding a servlet initializer to run it on wildfly) i commented out that bit and removed provided from spring-boot-starter-tomcat dependency and it started working. Adding here just in case some one else has the same issue

sarmahdi
  • 1,098
  • 4
  • 21
  • 61
0

My one got fixed using this dependency :

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
    </dependency>
Abhishek Sengupta
  • 2,938
  • 1
  • 28
  • 35