Spring boot deploy external tomcat - web-services

I'm using spring boot with a simple hello world controller. I would like to deploy it to external tomcat server. I've noticed that web.xml file is missing. I expected to see this file inside web-inf directory.
When running spring boot internally (with the internal tomcat of spring boot, it works. But I would like to deploy my app to external tomcat server.
After deploying the war file to external tomcat server, I can see the hello world in the available services list, but I can't use the hello world service - I get 404 error message instead.
I'm using maven, Jdk 1.8, IntelliJ
This is my pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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>org.springframework</groupId>
<artifactId>gs-spring-boot</artifactId>
<version>0.1.0</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.3.9</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.9.2.RELEASE</version>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
</plugins>
</build>
</project>
This is my Application class:
import java.util.Arrays;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.ApplicationContext;
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
}
}
What is the right way to deploy the hello world app to external tomcat service?

When deploying on tomcat, there should be a context path added by the container and that have to be included as first element path in your URL. Check tomcat startup logs to get the context path and retry calling the service as indicated.

If Spring boot app on external Tomcat is deployed successfully and no error are thrown, it is reachable not through localhost:8080/ but localhost:8080/your-deployed-war-file-name.
You can add finalName to your pom.xml to avoid adding versions to built war filename - Maven : How to avoid version appended to a war file in Maven?:
<build>
<finalName>${project.artifactId}</finalName>
</build>

Related

Unable to start embedded Tomcat On EC2 Instance

I am new to AWS, and I want to deploy my SpringBoot application on My LINUX EC2 instance with the AWS S3 bucket. And for that i have created a SpringBoot Application, Uploaded my Application's jar on S3 bucket successfully, I have installed Java 1.8 on my EC2 instance, I "wget" my jar on my instance. But when I am trying to run command java -jar <myfilename.jar> it gives error: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat.
Could you please tell me what should I do now?
Here is my POM.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.ab</groupId>
<artifactId>SpringBootTryApplication-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringBootTryApplication-2</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version> 5.2.1.Final</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
</project>
It says Java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/exc/InvalidDefinitionException. It means that this particular version of jackson-binder library does not have this particular class.
It Looks like the version 2.6 does not have this class.But the 2.9 does.
You should use the newer versions of jackson-databind library. The latest version seems to be 2.11.2 as of today.

Application error when creating simple web service using Spring Boot

I am getting below error when creating a simple web service that returns "hello" string
Whitelabel Error Page This application has no explicit mapping for
/error, so you are seeing this as a fallback.
My webservice endpoint:
#WebService
public class HelloWs {
#WebMethod
public String hello() {
return "hello";
}
}
My configuration class:
#Configuration
public class WebServiceConfig {
#Autowired
private Bus bus;
#Bean
public Endpoint endpoint() {
Endpoint endpoint = new EndpointImpl(bus, new HelloWs());
endpoint.publish("/hello");
return endpoint;
}
}
My pom.xml dependencies:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.2.7</version>
</dependency>
</dependencies>
My project structure:
If you are using mvn spring-boot:run then cxf web services are host at /services/*, Thus at url http://localhost:8080/services you will find list of the cxf endpoints, in your case it will be only one. And you get wsdl at location http://localhost:8080/services/hello?wsdl
If you are deploying to any app server add context path before services.

GRPC - .IllegalArgumentException: Jetty ALPN/NPN has not been properly configured

I am trying to spin up the GRPC server with TLS enabled in docker container on pods but getting below error during server start up
I am trying referring https://github.com/grpc/grpc-java/blob/master/SECURITY.md#transport-security-tls
Java : jdk1.8.0_131
OpenSSL version: OpenSSL 1.0.1e-fips
Exception:
*Exception in thread "main" java.lang.IllegalArgumentException: Jetty ALPN/NPN has not been properly configured.
at io.grpc.netty.GrpcSslContexts.selectApplicationProtocolConfig(GrpcSslContexts.java:174)
at io.grpc.netty.GrpcSslContexts.configure(GrpcSslContexts.java:151)
at io.grpc.netty.GrpcSslContexts.configure(GrpcSslContexts.java:139)
at io.grpc.netty.GrpcSslContexts.forServer(GrpcSslContexts.java:119)
at io.grpc.netty.NettyServerBuilder.useTransportSecurity(NettyServerBuilder.java:377)
at io.grpc.netty.NettyServerBuilder.useTransportSecurity(NettyServerBuilder.java:63)*
also want to know how I can test openssl approach locally ?
this is how I am trying to run the jar: java -jar -Denv=e1 app.jar
Below are the additional GRPC related POM dependencies specific to GRPC -I have in my POM:
-- extension --
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.4.0.Final</version>
</extension>
</extensions>
--- plugin ----
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.2.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.3.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
--- dependencies ---
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
<version>2.0.1.Final</version>
</dependency>
Can Openssl / jdk version be the problem ?
You need to add a dependency on Netty TCNative in order to get a correct security dependecy. From the SECURITY.md file for gRPC, you need to add the following:
<project>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
<version>1.1.33.Fork26</version>
</dependency>
</dependencies>
</project>
Note that this will change in the upcoming 1.4 release of gRPC to point to netty-tcnative-parent-2.0.1.Final
Although this question has been answered. I was in similar situation till today as i was not able to start the jetty server (Embedded).
This solution might help some who is using spring boot application with embedded jetty server.
Following should be the entries in pom.xml file.
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative</artifactId>
<version>2.0.6.Final</version>
<classifier>${os.detected.classifier}</classifier>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
<version>2.0.6.Final</version>
<classifier>${os.detected.classifier}</classifier>
</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.mortbay.jetty.alpn</groupId>
<artifactId>alpn-boot</artifactId>
<version>8.1.11.v20170118</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.alpn</groupId>
<artifactId>alpn-api</artifactId>
<version>1.1.3.v20160715</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
The version of alpn-boot should be dependent on the JDK that you use. Please refer following link for checking the version:
http://www.eclipse.org/jetty/documentation/current/alpn-chapter.html#alpn-versions
Once this done rebuild your project and add the following entry to your JVM arguments if you are using STS to start the spring boot application.
java -Xbootclasspath/p:%path_to_alpn_boot_jar%
And then start the server and it should work.
Thanks.

AWS Beanstalk: Cannot determine embedded database driver class

I have a spring boot application which runs just fine on my local instance (through Intellij) but while deploying on AWS BEanstalk, the application throws the following error (sorry about the formatting. This is how spring generated the exception):
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfig
uration$JdbcTemplateConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationExcept
ion: Could not autowire field: private javax.sql.DataSource org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$JdbcTemplateConfigur
ation.dataSource; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in cla
ss path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$NonEmbeddedConfiguration.class]: Bean instantiation via factor
y method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method
'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cann
ot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you
have database settings to be loaded from a particular profile you may need to active it (the profiles "aws" are currently active).
pom.xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-dynamodb</artifactId>
<version>1.10.56</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.my.app.path.MyApplication</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
application.properties
spring.profiles.active=aws
dynamodb.tablename=my_dynamodb_table
application-aws.properties
spring.profiles.active=aws
The application uses a table in dynamodb. Could this be because I might need to set permissions in AWS to allow beanstalk to talk to dynamodb? If so, please let me know how to do that.
My EC2 instance is tomcat8 type.
Found the solution to my question on this post. See the answer by #user672009.
Just add this to your pom.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.156</version>
</dependency>

Why does Maven Jetty Plugin not find a class in a standard jetty jar

I'm using Jetty 9.0.4v20130625 running it using the maven-jetty-plugin. I have implemented my own LoginService class to handle users logging in to a realm. On one of the lines, I attempt to use the org.eclipse.jetty.util.security.Credential class but during execution it throws a NoClassDefFoundError on that line.
My target directory contains everything being deployed to the Jetty instance. Within it the WEB-INF/lib folder does not contain the jetty-util-9.0.4.v20130625.jar as expected because the plugin should already have it so I believe that rules out conflicting jars. So what could be causing the jetty instance to not find this jar?
I am using eclipse, and it shows no errors in the code. I set it up as a Maven project and Maven handles the dependencies. I set it to not to package the jetty jars as they should be provided by Jetty when deployed. Here is my pom.xml:
<project ...>
...
<packaging>war</packaging>
...
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>9.0.4.v20130625</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.11.2</version>
</dependency>
</dependencies>
<build>
<finalName>...</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.0.4.v20130625</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<webApp>
<contextPath>/...</contextPath>
</webApp>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>Test Realm</realm-name>
<form-login-config>
<form-login-page>/loginAuth.html?param=redirect</form-login-page>
<form-error-page>/loginAuth.html?param=failed</form-error-page>
</form-login-config>
</login-config>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-plugin</artifactId>
<version>1.8.1</version>
<configuration>
<connectionType>developerConnection</connectionType>
</configuration>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>install</phase>
<configuration>
<tasks>
<ant target="deploy" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.50</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-jsch</artifactId>
<version>1.9.2</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
I checked to be sure the plugin depends on the jetty-util.jar and it does as seen here
Something that may be part of the problem: To implement a new LoginService interface class, I am extending the MappedLoginService class which already implements LoginService (it's in the Jetty jars) and I'm overriding some of its methods. Could that be causing a problem?
Jetty hides almost all of its implementation classes from the webapp's classloader. If you need access to them from inside your webapp, then you need to put them into your webapp's WEB-INF/lib (in your case add a dependency for jetty-util jar).
This classloading mechanism is described here: http://www.eclipse.org/jetty/documentation/current/jetty-classloading.html
BTW, the configuration for the jetty-maven-plugin from your pom.xml seems to contain some lines from web.xml (i.e. those inside the elements). I believe maven ignores configuration it doesn't understand, but perhaps things are not configured the way you think they are? Also, I don't see any setup for using your custom LoginService.