неделя, 6 септември 2015 г.

How to deploy spring boot on wildFly AS

Few weeks ago I faced an issue of deploying spring boot application on wildFly  application server. After achieve most of you ordinary routine task usually you say "I'm so relived that I get rid of this! Lets go ahead on next issues." But that's not the point an open source geek would stay with. Based on this, I was urged to write this blog post by one of our BGJUG guys Nayden Gochev.

Actually this task is not so difficult to be achieve but you have to know what components need a spring boot web application.
After few hours roaming around github public repositories with help of Mitia Alexandrov other jug geek we came across a solution to deploy spring boot on wildFly AS.

On this blog post we will code a simple spring boot web service that  is available by the following github repo: https://github.com/IvayloZashev/spring-restful-ws-example.

Pre-overview of the application:
Lets start with the pom.xml file.
We will focus on the important elements only so at first time is the element
 <packaging>war</packaging>  

Spring boot is distributed with embedded Tomcat web container and that's why the default packaging composes jar file. We are deploying on wildFly so you have to add this element to your pom.

After that you should add the parent project:
 <parent>  
     <groupId>org.springframework.boot</groupId>  
     <artifactId>spring-boot-starter-parent</artifactId>  
     <version>1.3.2.RELEASE</version>  
 </parent>  

This element adds most of the dependencies that spring boot needs at compile time.

In Dependencies section we have:
 <dependency>  
       <groupId>org.springframework.boot</groupId>  
       <artifactId>spring-boot-starter-web</artifactId>  
       <exclusions>  
         <exclusion>  
           <groupId>org.springframework.boot</groupId>  
           <artifactId>spring-boot-starter-tomcat</artifactId>  
         </exclusion>  
       </exclusions>  
 </dependency>  

Dependency with artifact id spring-boot-starter-web initializes the web context of the spring boot application and provides web api of spring boot framework.
The version of this dependency is not explicitly defined because we are extending version from the parent dependency.

And here comes the big point...

Exclusion of dependency with artifact id spring-boot-starter-tomacat is needed because we will deploy the war file on wildFly. If this exclusion is missed you will get the exception with code "JBAS014671: Failed services".
Which means that Tomcat API class WsServerContainer cannot be cast to wildFly API class ServerWebSocketContainer. And deployment processe interupts with above error.

And finally we need:
 <dependency>  
     <groupId>javax.servlet</groupId>  
     <artifactId>servlet-api</artifactId>  
     <version>2.5</version>  
 </dependency>  
to transmit http requests in controller layer.

Lets move on to Java code. Before start coding anything you should create a package in project's java directory (src/main/java/). If you miss this you're likely to get the console output warning message:
Your ApplicationContext is unlikely to start due to a @ComponentScan of the default package.

And, Yes, your application won't start.

We have several model entities that represents basic arithmetic operations over two integer numbers: sum, subtract, multiply and to dive into http requests all-in-one.
Business logic for the entities are implemented in bean named FiguresService annotated with @Service.
When you play with spring framework inversion of control it's a good practice to use autowiring by static field e.g NAME because spring autowires faster by static field rather than by class.

And here comes the long waited bean annotated with @RestController which will intercept http requests to the server. The source code for this bean is available here.
@RestController annotation is available since spring 4.0 release. This annotation is annotated itself by @Controller and @ResponseBody.
In this controller we are autowiring bean named FiguresService by NAME
   @Autowired  
   @Qualifier(FiguresService.NAME)  
   FiguresService figuresService;  

We are assigning parameters to the request by @RequestParam but there are alternatives as well e.g @PathVariable and @RequestBody.

In the class with main method we have the following code:
 @SpringBootApplication  
 @ComponentScan  
 public class Application extends SpringBootServletInitializer {  
   public static void main(String[] args) {  
     SpringApplication.run(Application.class, args);  
   }  
 }    

Here is the second big point in this application. Our Application class extends class SpringBootServletInitializerBy doing this we are producing support for spring servlet and configuring our application to be launched by the servlet container, in our case wildFly AS. And as we see from the API docs is needed to build a war file and deploy it.

And that's it :) You only have to build a war file and deploy it to your wildFly AS.

About me


With fewer words that I expected: My name is Ivaylo Zashev. I am computer engineer. I work for a company Gopler and I am passionate member of Bulgarian Java User Group.