We have developed RESTful services using Spring Boot in our last tutorial. Now we will learn How to deploy Spring Boot application in IBM Liberty and WAS 8.5. Many of us are still using IBM Application Servers and it’s very important to understand how we can deploy our spring boot code there.
Why ?
Since Spring Boot’s main objective is to support Microservices and Cloud Native Applications,it includes embedded Tomcat\Jetty. IBM is also moving towards a very similar direction with their Liberty Profile Application Server and Bluemix. Now Liberty has Maven plugin to create, build and deploy Spring Boot Application to IBM Liberty Profile Application Server, which is either hosted locally or remotely using Bluemix. They have also provided similar support for Cloud Foundry (Could Native). So it has become very crucial to understand how to deploy Spring Boot application in IBM Liberty and WAS 8.5 (Websphere Application Server 8.5).
Moreover, many of our existing infrastructure is already using Websphere Application Server 8.5 / IBM Liberty profile. If we want to enable Spring Boot with our current infrastructure we need to also find a way to deploy the application there.
I am not discussing in detailed on WebLogic/JBOSS (Wildfly) here, the same mechanics would apply there as well.
How ?
There are mainly two ways to configure & deploy Spring Boot application in IBM Liberty Profile Application Server. Here are the approaches we shall experiment with.
- Configure Spring Boot using spring-boot-starter-parent
- Configure Spring Boot Application using net.wasdev.wlp.starters.springboot
Once our Spring Boot Application is working in IBM Liberty Profile, we will then deploy the application in IBM WebSphere Application Server 8.5.
P.S – The Java code would stay same across each deployment process, however the configuration and pom
file would be different.
IBM Liberty Profile
spring-boot-starter-parent
As you have already created some Spring Boot Application by now, you can find that in each pom file has a parent artifact id as spring-boot-starter-parent
. We will keep that as is and deploy our app.
Make sure you have the latest version (8.5.5.9, at the time to writing this blog) of IBM Liberty Profile, also its good to have the full JEE server. If you are not sure check the read-me file for the server version and run the following command to install the full JEE7 profile.
./installUtility install javaee-7.0
Changes to Maven Configuration File
Since we were using embedded Tomcat server we were using a jar file to run our app, now we need to create a war file to deploy that to IBM Liberty Server. So at first change packaging to war
from jar
Add the Tomcat starter to exclusion list.
1 2 3 4 5 6 |
<exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> |
Since we need Servlet 3.1 we need to add the dependency here.
1 2 3 4 5 6 |
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> |
In case you are using an old application server and want to use Servlet 3.0, use the following dependency instead.
1 2 3 4 5 6 |
<dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency> |
Here is my pom file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.adeveloperdiary</groupId> <artifactId>springweb</artifactId> <version>1.0</version> <packaging>war</packaging> <name>spring_web</name> <description>springweb</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <start-class>com.adeveloperdiary.ServletInitializer</start-class> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <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> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-actuator</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> <configuration> <skip>true</skip> </configuration> </execution> </executions> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> </plugin> </plugins> </build> </project> |
Change the Code
Still now we had the main
method as the starting point of our Spring Boot Application, however since we are using a WAR
file we can’t leverage that. We need to change our main class to following. I also have a REST service to test the app.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@SpringBootApplication(exclude = MessageSourceAutoConfiguration.class) public class ServletInitializer extends SpringBootServletInitializer { /*public static void main(String[] args) { SpringApplication.run(ServletInitializer.class, args); }*/ @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(ServletInitializer.class); } } @RestController class RESTController { @RequestMapping("/") public String hello() { return “<H1>Spring Boot Application from adeveloperdiary.com</H1>”; } } |
Liberty Server Configuration
There isn’t anything to update/add in the server.xml
of the Liberty Profile. Here is my version.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<server description="new server"> <!-- Enable features --> <featureManager> <feature>javaee-7.0</feature> <feature>adminCenter-1.0</feature> <feature>localConnector-1.0</feature> </featureManager> <variable name="defaultHostName" value="localhost" /> <!-- Define an Administrator and non-Administrator --> <basicRegistry id="basic"> <user name="admin" password="adminpwd" /> <user name="nonadmin" password="nonadminpwd" /> </basicRegistry> <!-- Assign 'admin' to Administrator --> <administrator-role> <user>admin</user> </administrator-role> <keyStore id="defaultKeyStore" password="Liberty" /> <httpEndpoint host="*" httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint" /> <!-- Automatically expand WAR files and EAR files --> <applicationManager autoExpand="true" /> <applicationMonitor updateTrigger="mbean" /> </server> |
Deploy To Liberty Profile
You can manually drop the war file to the dropins folder once liberty has started it will install the app.
In case you are using eclipse, just add the war to the server, the app will be automatically compiled. One quick tip here is, if you don’t create the spring boot app from STS by selecting war packaging option, you may not see the war file listed here.In that case you need to build using Maven and deploy the war manually.
In case you are using IntelliJ IDEA, you need to add a Liberty server profile and add Maven build then deploy artifact. Every time you start the server or redeploy the app it will automatically compile everything and then deploy the war file.
Once you access the URL of the deployed app, Spring Boot will initialize and load the related configurations.
net.wasdev.wlp.starters.springboot
IBM has recently started supported Spring Boot using net.wasdev.wlp.starters.springboot
. Let me provide you the pom I will be using here.
If you look closely there are many differences of packages here and you can see IBM provided starters has been used here.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>myParentGroupId</groupId> <artifactId>SpringBootLiberty</artifactId> <version>1.0</version> <packaging>war</packaging> <scm> <connection>scm:git:git@github.com:WASdev/tool.artisan.core.git</connection> <developerConnection>scm:git@github.com:WASdev/tool.artisan.core.git</developerConnection> <url>git@github.com:WASdev/tool.artisan.core.git</url> </scm> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <repositories> <repository> <id>liberty-starter-maven-repo</id> <name>liberty-starter-maven-repo</name> <url>http://liberty-starter.wasdev.developer.ibm.com/start/api/v1/repo</url> </repository> </repositories> <dependencies> <dependency> <groupId>net.wasdev.wlp.starters.springboot</groupId> <artifactId>provided-pom</artifactId> <version>0.0.1</version> <type>pom</type> <scope>provided</scope> </dependency> <dependency> <groupId>net.wasdev.wlp.starters.springboot</groupId> <artifactId>runtime-pom</artifactId> <version>0.0.1</version> <type>pom</type> <scope>runtime</scope> </dependency> <dependency> <groupId>net.wasdev.wlp.starters.springboot</groupId> <artifactId>compile-pom</artifactId> <version>0.0.1</version> <type>pom</type> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-actuator</artifactId> <version>1.3.3.RELEASE</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.6</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> <packagingExcludes>pom.xml</packagingExcludes> </configuration> </plugin> </plugins> </build> </project> |
The Java code we changed previously will stay same, however IBM has provided support for defining Context root and web.xml
. Also you can add any html file. You need to create a folder named webapp
at the same level of java
and resources
and add following files there. Here my directory structure.
You can now define the context root in the ibm-web-ext.xml
file.
1 2 3 4 5 6 7 |
<web-ext xmlns="http://websphere.ibm.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-ext_1_0.xsd" version="1.0"> <context-root uri="/SpringBootLiberty"/> </web-ext> |
The web.xml
is a basic one I will be using
1 2 3 4 5 6 7 8 9 |
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <display-name>Spring Boot Liberty</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app> |
Also added an index.html
file to make sure its working as expected. When you build your app using the above pom file, it will add the webapp folder in your war file.
I have created the pom specific for development perspective. You can find more details here (http://liberty-app-accelerator.wasdev.developer.ibm.com/).
Here is my IntelliJ configuration.
Once you run the server you will get following logs.
IBM WebSphere Application Server 8.5
In order to deploy Spring Boot Application to IBM WebSphere Application Server 8.5 sever you need to have the latest fix pack installed to get the most compatibility. At the time of writing this post the latest fix pack is 8.5.5.9
, please make to download and install it.
I have also tested using JDK 6,7 & 8, all of them are working fine. You need to generate the war file using Maven and deploy that to server. Use the above pom files to create the war file.
When using spring-boot-starter-parent
, you need to manually downgrade the Servlet version to 3.0
since WAS 8.5.5.9 supports only till Servlet 3.0 and not 3.1. You need to use the following dependency.
1 2 3 4 5 6 |
<dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency> |
I was able to make both spring-boot-starter-parent
& net.wasdev.wlp.starters.springboot
working in IBM WebSphere Application Server 8.5. If you notice we had defined start-class
in the properties section, WAS will automatically use it to load the Servlet Initializer during server startup.
You will not be able to use Rational Application Developer with the build, you probably need eclipse or IntelliJ IDEA for your development.
Conclusion
You will probably be using embedded Tomcat during your development and use a Maven build to create the WAR specific for Liberty or WAS 8.5. There might be conflicts with older version of the jars when you use WAS 8.5, however Liberty supports most of the latest versions. We will see more compatibility between Spring Boot and Liberty, however may not be so much for WAS 8.5.
This post is the 4th part of Getting Started with Spring Boot Series. Find all the parts here.
- An Introduction to Spring Boot
- How to Create Spring Boot Application Step by Step
- How to create RESTFul Webservices using Spring Boot
- How to deploy Spring Boot application in IBM Liberty and WAS 8.5
Sridhar says
Hi,
Your article was interesting.
I am able to deploy Spring boot app to WAS Liberty Profile.
I am now working on deploying Reverse Proxy Component (Using Spring ZUUL) , Service Registry Component (Using Spring Netflix EUREKA) also to WAS Liberty Profile.
But, I get error when accessing the deployed spring boot service via the ZUUL Proxy.
I believe it has something to do with packaging and deployment to WAS Liberty Profile.
Can you please help me on this.
I have a sample ATOMIC Service, ZUUL Service and EUREKA Service deployed to separate WAS Liberty Profile servers.
I have shared the code for these services in the github repos.
–For ZUUL Reverse Proxy Service
https://github.com/bsridhar123/ZUUL
–For ATOMIC Service which is proxied by ZUUL
https://github.com/bsridhar123/AtomicService
–For EUREKA Service Registry Service
https://github.com/bsridhar123/Eureka
Also, I have the logs folder where I have added the logs obtained when trying to make a lookup of the service via ZUUL Service.
https://github.com/bsridhar123/ZUUL/blob/master/logs/PROXY_ATOMIC.txt
Also, the WAS Libery Profile server.xml for each of the respective services are in the folders below.
–For ATOMIC Service
https://github.com/bsridhar123/AtomicService/blob/master/server-config/server.xml
–For ZUUL Service
https://github.com/bsridhar123/ZUUL/blob/master/server-config/server.xml
–For EUREKA Service
https://github.com/bsridhar123/Eureka/blob/master/server-config/server.xml
Can you please have a look and help me in identifying the cause of the error.
Thanks,
Sridhar
Ram s says
Excellent Article, thanks for putting the this article in various stages. It was very helpful to start from the basics and building the microservices with integration together.
Keep up the good work !!!
sri123 says
Its really very nice articular for beginners, thank you for your post.
Ramani says
nice article step by step
Stephan Knitelius says
Why?
You are dealing with fully Java EE 7 (Liberty) / 6 (WAS Traditional) compliant application servers.
Just go ahead and use the provided Java EE stack and deploy a light weight skinny WAR/EAR to your runtime.
The best thing of all – it’s all fully integrated and tested for you.
So be a champ and learn about the target environment at hand.
sulthana says
I am deploying this example in WAS 8.5, here is the error I am getting.
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:185)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:158)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:130)
Aaron Yang says
good article, let me quick start spring boot using liberty. Keep up ur great work!
Aaron Yang says
good article, let me quick start spring boot using liberty. Keep up ur great work!
Thomas says
Hello,
i was able to start a spring boot application in a liberty (JEE8 Liberty Server in Eclipse) by deploying a war file with the net.wasdev.wlp.starters.springboot approach.
But the port (server.port in application.properties) will not open.
(I think this is because no spring internal tomcat in a liberty server)
How to open the port?
(of course for working REST requests)
Stefan says
Hello,
I was able to start two spring boot apps in a liberty with the net.wasdev.wlp.starters.springboot approach.
I can see the “spring logo” in the log twice.
But there a no ports open from the spring boot, no rest controller can be called. How to achieve this?
Kind regards