How to deploy swagger generated spring code (Tomcat) - spring

I used the example given by SwaggerCodeGen to create a Server via SpringBoot.
I build the project with maven and run it local. Everythings works fine.
Now I want to deploy this project on a tomcat (version 7).
So I changed the packing from jar to war
<packaging>war</packaging>
and moved the *.war file to tomcat\webapps folder
I tried to run
localhost:8080/app
which return an 404
same with
localhost:8080/app/swagger-ui.html
localhost:8080/v1/app/
localhost:8080/v1/app/api-docs
Unfortunatly, I have got no experience with tomcat.
The Project doesn't contain a web.xml. Is it necessary?
Do I need to create a Servlet?
Any help would be appreciated.

In your POM you need:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
and
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.9</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
Your SpringBoot Application should also look like this:
public class SpringBootServiceApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(SpringBootServiceApplication .class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringBootServiceApplication .class);
}
}

Related

How to self start spring app without writing a main method?

So is there a way to initialize and start a command line Spring app without writing a main method. It seems like all such main methods have the same form
public static void main(final String[] args) throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml", Boot.class);
SomeService someService = (SomeService) applicationContext.getBean("someService");
someService.bar();
}
I suppose that's not complicated, but has someone found a way to provide a way to just specify the context.xml at the command line or, better yet, in a manifest file?
The goal here is to simplify the creation of spring applications as executable jars. I hope that I can specify some utility class as the Main-Class in the manifest. I suppose I would also need to specify the starting point for the app, a bean and a method on it where begins the process.
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.stackoverflow</groupId>
<artifactId>stackoverflow-autostart-spring-app</artifactId>
<version>0.1</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.5.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.stackoverflow.spring.autostart.Autostart</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Write a simple SpringMain which takes an arbitrary number of xml and properties files as the arguments.java -cp myapp.jar util.SpringMain context.xml
You then use the lifecycle attributes (init-method) on your relevant beans to kick-start the application

Run a spring boot app located on another project before running karate tests? [duplicate]

This question already has an answer here:
Is there a way to run Karate tests as an integration test suite against a pre-booted spring boot server?
(1 answer)
Closed 2 years ago.
I'm trying to build some karate tests to a spring boot application. Here's the project structure :
co-training-backend (parent)
|_ co-training-rest (maven module)
|_ co-training-rest-karate (maven module)
If i run the server and launch the karate tests everything works fine. Now i'd like to automate that by running the server from the rest-karate module.
Here's my config :
class CoTrainingTests {
private static ConfigurableApplicationContext context = null;
#BeforeAll
public static void setUp() throws Exception {
context = SpringApplication.run(RestBootstrap.class, new String[]{});
}
#Karate.Test
Karate testAll() {
return Karate.run().relativeTo(getClass());
}
#AfterAll
public static void tearDown() throws Exception {
if(context!=null)
context.stop();
}
}
pom.xml
<artifactId>co-training-rest-karate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<junit-jupiter.version>5.6.2</junit-jupiter.version>
<karate.version>0.9.6</karate.version>
<maven.compiler.version>3.8.1</maven.compiler.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.intuit.karate</groupId>
<artifactId>karate-apache</artifactId>
<version>${karate.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.intuit.karate</groupId>
<artifactId>karate-junit5</artifactId>
<version>${karate.version}</version>
<scope>test</scope>
</dependency>
<!-- this is the spring boot rest project -->
<dependency>
<artifactId>co-training-rest</artifactId>
<groupId>com.co.training</groupId>
<version>1.0.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<testResources>
<testResource>
<directory>src/test/java</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<encoding>UTF-8</encoding>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<argLine>-Dfile.encoding=UTF-8</argLine>
</configuration>
</plugin>
</plugins>
</build>
If i run the tests from the command line i have this maven compiler error :
mvn clean test
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:testCompile (default-testCompile) on project co-training-rest-karate: Compilation failure
[ERROR] /home/salto/tutorials/co-training/co-training-backend/co-training-rest-karate/src/test/java/cotraining/CoTrainingTests.java:[3,28] package com.co.training.rest does not exist
but this class exists in the rest dependency :
ls /home/salto/.m2/repository/com/co/training/co-training-rest/1.0.0-SNAPSHOT/co-training-rest-1.0.0-SNAPSHOT.jar
/home/salto/.m2/repository/com/co/training/co-training-rest/1.0.0-SNAPSHOT/co-training-rest-1.0.0-SNAPSHOT.jar
any idea ?
You can use the integration-test phase of the maven lifecycle:
pre-integration-test: start the co-training-rest module
integration-test: run you karate integration tests
post-integration-test: shut down the co-training-rest module and do
any other necessary cleanup

Jersey fails when creating uber jar with maven-assembly-plugin

I have created a maven jersey starter webapp. Also I have embedded jetty server in my app using jetty plugin.
My project is working fine when I run my project using mvn jetty:run command.
But when I package my project using mvn clean package command and run the jar file which has name jar-with-dependencies the project throws this exception while returning a json response from a jersey resource.
SEVERE: MessageBodyWriter not found for media type=application/json, type=class com.nitish.freecharge.model.Count, genericType=class com.nitish.freecharge.model.Count.
Here is my pom.xml file
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.nitish.freecharge</groupId>
<artifactId>wordcount</artifactId>
<packaging>war</packaging>
<version>2.0</version>
<name>wordcount</name>
<build>
<finalName>wordcount</finalName>
<resources>
<resource>
<directory>src/main/java</directory>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/webapp</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.3.0.v20150612</version>
<configuration>
<scanIntervalSeconds>5</scanIntervalSeconds>
<webApp>
<contextPath>/wordcount</contextPath>
</webApp>
<httpConnector>
<!--host>localhost</host -->
<port>9999</port>
</httpConnector>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>package-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<finalName>awesomeProject</finalName>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
<archive>
<manifest>
<mainClass>App</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.3.8.v20160314</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.3.8.v20160314</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
</dependency>
</dependencies>
<properties>
<jersey.version>2.22.2</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
I have created my Main Driver class as App.java in default package. Here is my App.java content
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
public class App {
public static void main(String []gg){
Server server = new Server(9999);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
context.setContextPath("/");
server.setHandler(context);
ServletHolder jerseyServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/wordcount/*");
jerseyServlet.setInitOrder(1);
jerseyServlet.setInitParameter("jersey.config.server.provider.packages","com.nitish.freecharge.resources");
try {
System.out.println("Starting the server..");
server.start();
System.out.println("Server started");
server.join();
} catch(Exception e) {
System.out.println("Exception in starting the server ");
e.printStackTrace();
}
}
}
Here is my only jersey resource class which gets executed when I access my project url after starting the server :
package com.nitish.freecharge.resources;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import com.nitish.freecharge.dao.FileDAO;
import com.nitish.freecharge.model.Count;
/**
* Root resource (exposed at "count" path) which handles HTTP GET method and returns the count value;
*/
#Path("/count")
public class CountResource {
private FileDAO fileDAO=new FileDAO();
/**
* Method handling HTTP GET requests. The returned object will be sent
* to the client as "application/json" media type.
*
* #return String that will be returned as a application/json response.
*/
#GET
#Produces(MediaType.APPLICATION_JSON)
#QueryParam("query")
public Response getWordCount(#QueryParam("query")String query) {
Error error=null;
Count count=null;
try{
if(query!=null){
query=query.trim();
if(query.length()>0 && query.matches("^[A-Za-z]+$")){
long c=fileDAO.getCount(query.toLowerCase());
count=new Count(c);
}else{
error=new Error("Some Error Occured.Please Try Again With a new word!");
}
}else{
error=new Error("Some Error Occured.Please Try Again!");
}
}catch(Exception e){
error=new Error(e.getMessage());
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(error).build();
}
if(count!=null){
return Response.status(Status.OK).entity(count).build();
}else{
return Response.status(Status.BAD_REQUEST).entity(error).build();
}
}
}
After packaging and run the complete embedded project using command
java -jar awesomeProject.jar
I get this output on the server prompt
I have tried a lot and unable to package my embedded webapp in such a way that this issue gets resolved. I am new to maven and packaging. Kindly Help where I am committing mistake.
If you look inside the MOXy jar, you will see a folder META-INF/services. In that folder, you will see a file named org.glassfish.jersey.internal.spi.AutoDiscoverable. The content of that file should be a single line
org.glassfish.jersey.moxy.json.internal.MoxyJsonAutoDiscoverable
What this file is for is to allow Jersey to discover the MoxyJsonAutoDiscoverable, which registers MOXy for Jersey. This service loader pattern allows Jersey to discover features and register them, without us having to register them ourselves.
The problem this poses when creating an uber jar is that there may be multiple jars with the same file, as different jars have different features to discover, but the file needs to be that exact name as that is how the service loader pattern works.
So you have a bunch of jars with the same file, but when you create the uber jar, you cannot have multiple files with the same name. It's just not possible. So only one of the files gets put into the final jar. Which one.. who knows. But that means that if MOXy's files is not that one file then its feature will not be auto-discovered, and we need to register it ourselves. So the classes are packaged in the uber jar, but the main feature component is just not registered. You could just register it yourself
jerseyServlet.setInitParameter("jersey.config.server.provider.classnames",
"org.glassfish.jersey.moxy.json.MoxyJsonFeature");
but what about all the other possible features that are possibly left out because their auto-discoverable file is not included?
For this reason, instead of the assembly plugin, you should use the maven-shade-plugin, which has transformers that allow us to concatenate the contents of service files into one file.
The configuration would look something like
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.YourApp</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
The ServicesResorceTransformaer is what concatenates the files. This particular configuration of the plugin was taking from the Dropwizard getting started. You may want to check that out for further explanation.

jackrabbit: Why do i get javax.jcr.RepositoryException: Unable to access a repository when I execute a runnable jar file and not on netbeans?

I have created a runnable jar file from an existing maven project on netbeans,
which contains all dependencies included in pom.xml
When I run it on Netbeans it work:
stampa
adsa
stampa2
when instead I run it from the runnable jar file I get this error:
java -jar ./Prova-1.0-SNAPSHOT-jar-with-dependencies.jar
stampa
adsa
Exception in thread "main" javax.jcr.RepositoryException: Unable to access a repository with the following settings:
org.apache.jackrabbit.repository.uri: http://localhost:8082/server
The following RepositoryFactory classes were consulted:
org.apache.jackrabbit.core.RepositoryFactoryImpl: declined
Perhaps the repository you are trying to access is not available at the moment.
at org.apache.jackrabbit.commons.JcrUtils.getRepository(JcrUtils.java:223)
at org.apache.jackrabbit.commons.JcrUtils.getRepository(JcrUtils.java:263)
at com.mycompany.leggitutto.Source.main(Source.java:38)
I don't get it.
Why on netbeans the RepositoryException is not thrown?
The java code is the same, the build is successful and the Run is different!!!
public static void main(String[] args) throws Exception
{
System.out.println("stampa");
System.out.println("adsa");
Repository repository1 = JcrUtils.getRepository("http://localhost:8082/server");
Session session1 = repository1.login(new SimpleCredentials("admin","admin".toCharArray()), "default");
System.out.println("stampa2");
}
Jackrabbit server is running at
"http://localhost:8082/server",
I have even checked it on firefox, and the repository is reachable.
I'd be glad if someone can help me to figure this out :)
I solved it,
I changed maven plugin in pom.xml in onejar-maven-plugin and It works now.
Appearently, using maven-shade-plugin or maven-assembly-plugin, not every dependencies were added to the final jar "executable".
This pom.xml is working YEAH!!!
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.dstovall</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<configuration>
<mainClass>Valid.Main.Class</mainClass>
<!-- Optional -->
<onejarVersion>0.97</onejarVersion>
<!-- Optional, default is false -->
<attachToBuild>true</attachToBuild>
<!-- Optional, default is "onejar" -->
<classifier>onejar</classifier>
</configuration>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<pluginRepositories>
<pluginRepository>
<id>onejar-maven-plugin.googlecode.com</id>
<url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
</pluginRepository>
</pluginRepositories>

Maven failsafe plugin will not run test classes annotated with JUnit Category

I have an interface like this:
public interface IntegrationTest {
}
I configure the failsafe plugin like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.14</version>
<configuration>
<groups>acme.test.IntegrationTest</groups>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
If I then create an integration test like this
#Category(IntegrationTest.class)
public class ExampleClassIntegrationTest {
#Test
public void slow_and_painful_test() {
This test will not run.
If I however name the class according to the Inclusions and Exclusions of Tests
**/IT*.java
**/*IT.java
**/*ITCase.java
Like so:
#Category(IntegrationTest.class)
public class ExampleClassIT {
#Test
public void slow_and_painful_test() {
The test runs fine. Why do I have to name the test AND have an annotation when i use the groups-tag? Am I missing something? The documentation on using JUnit states that you can use the Category annotation at the class level.
Thats because these are the default java classes which fail safe plugin includes when executed.
You can however over ride this in your pom with tag :
E.g
<includes>
<include>**/*.java</include>
</includes>
To include all the java files.
You should either add JUnit as a dependency (>4.8) which is already done or in particular add the following to your failsafe-plugin configuration:
<plugins>
[...]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.14.1</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.14.1</version>
</dependency>
</dependencies>
</plugin>
[...]
</plugins>
But i assume it will not change the situation.

Resources