How to run spring batch application without spring boot maven plugin - spring

Is it possible to run a spring batch application without spring boot maven plugin?
I need to run the application on another server and transferring a big jar (with spring dependencies) is time consuming. For this reason I want to compile and create a jar without spring dependencies included inside the jar and run it from command line.

If you want to create a simple JAR without spring boot dependencies, remove spring-boot-plugin from build.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
Above snippet should not be present in your pom.xml.
With this, fat/uber jar won't be created.
To run built jar:
java -cp MyJar.jar:lib/* com.somepackage.subpackage.Main
Where your libraries are contained in lib directory relative to current directory and MyJar.jar is the name of the jar built with maven.

Related

Intellij Spring maven install error "package does not exist"

Intellij version : Community 2019.2.3
Maven : 3.6.2
Spring : 2.2.0
I am trying to create a very simple Spring maven project with two sub-modules (one independent and another one dependent on independent one).
Root module - testmultimodule
Independent module - independent
Dependent module - dependent
testmultimodule pom.xml has all Spring related declaration and module definition
<modules>
<module>independent</module>
<module>dependant</module>
</modules>
Independent poom.xml is simplest and . only has parent maven declaration
<parent>
<artifactId>testmultimodule</artifactId>
<groupId>in.org.app</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
dependent module pom.xml has the dependency declaration as below to independent module
<dependencies>
<dependency>
<groupId>in.org.app</groupId>
<artifactId>independent</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
I have created a Test class under dependent module and using a User object from independent module. Initially, without the above dependency declaration, asa usual there was compilcation error.
As soon as I add the dependency and builld the project within Intellij IDE with the option "Build Prooject" option from "Build" menu, it successfully builds.
However, if I try to use Maven install option within Intellij right side window option. It always fails stating Error:(3,33) java: package in.org.app.independent.bo does not exist .
I am providing the GitHub URL for the test project , if you want to take a look and test by yourself.
GIT URL:
https://github.com/DhruboB/testmultimodule
I have tried all sort of tweaking found in internet so far e.g.
clearing Intellij Cache & restarting, mvn -U clean install, mvn scope verification, proxy etc.
Any further idea to resolve this? I need to solve this in the Community version of Intellij.
Your parent project includes the definition for the spring-boot-maven-plugin. This leads to each project defining this as a parent to be repacked to an executable JAR by this plugin. This repackaged JAR isn't useable as a dependency in another project.
Either you need to change the configuration of the spring-boot-maven-plugin for the project you want to use as a dependency. This is explained here in the Spring Boot Reference Guide. You now basically have 2 jars from this project, one plain and one executable.
If you don't need that project to be an executable JAR file then just move the spring-boot-maven-plugin to the project that needs to be. All other projects will no be basic JAR files again.
See also How to add a dependency to a Spring Boot Jar in another project?

Utility Jar using Spring Boot

Created a custom jar using spring boot and this is using for CRUD operations on a database table.The purpose is used to make this a utility jar, so that other services or applications can use this jar for any operations on that table. Following are the steps I followed:
1). Added this jar entry in pom.xml of a REST SERVICE and build got successfully.
2). Autowired the service class of Utility jar inside the controller of REST SERVICE.
But when I started the REST SERVICE (service is developed on spring boot), I got the error as 'the ****controller can require a bean of type *****serviceUtility. Consider defining a bean of type in your configuration'. But I am not able to see any configuration class inside the rest service and it is using application.yml for datasource related things. I am new to Spring and Spring Boot. Could any one guide me how to configure the utility jar in external services.
It is hard to tell without source code, but Spring Boot jars do not by default work as utility jars. The packaging is different. To get a Spring Boot jar to work as a utility jar within another project, you'll want to configure the build plugin like this :
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
Which is described here:
https://docs.spring.io/spring-boot/docs/current/maven-plugin/examples/repackage-classifier.html
If you are using spring boot , by default , the utility jar will not move all its dependencies .
You can add all the dependencies in the pom.xml for the Rest service .
Else you end up packaging some core modules twice increasing the size of your jar .

FlinkMLTools NoClassDef when running jar built with maven

I'm working on a recommender system using Apache Flink. The implementation is running when I test it in IntelliJ, but I would like now to go on a cluster. I also built a jar file and tested it locally to see if all was working but I encountered a problem.
java.lang.NoClassDefFoundError: org/apache/flink/ml/common/FlinkMLTools$
As we can see, the class FlinkMLTools used in my code isn't found during the running of the jar.
I built this jar with Maven 3.3.3 with mvn clean install and I'm using the version 0.9.0 of Flink.
First Trail
The fact is that my global project contains other projects (and this recommender is one of the sub-project). In that way, I have to launch the mvn clean install in the folder of the right project, otherwise Maven always builds a jar of an other project (and I don't understand why). So I'm wondering if there could be a way to say explicitly to maven to build one specific project of the global project. Indeed, perhaps the path to FlinkMLTools is contained in a link present in the pom.xml file of the global project.
Any other ideas?
The problem is that Flink's binary distribution does not contain the libraries (flink-ml, gelly, etc.). This means that you either have to ship the library jar files with your job jar or that you have to copy them manually to your cluster. I strongly recommend the first option.
Building a fat-jar to include library jars
The easiest way to build a fat jar which does not contain unnecessary jars is to use Flink's quickstart archetype to set up the project's pom.
mvn archetype:generate -DarchetypeGroupId=org.apache.flink \
-DarchetypeArtifactId=flink-quickstart-scala -DarchetypeVersion=0.9.0
will create the structure for a Flink project using the Scala API. The generated pom file will have the following dependencies.
<dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-scala</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-scala</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients</artifactId>
<version>0.9.0</version>
</dependency>
</dependencies>
You can remove flink-streaming-scala and instead you insert the following dependency tag in order to include Flink's machine learning library.
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-ml</artifactId>
<version>0.9.0</version>
</dependency>
When you know build the job jar with mvn package, the generated jar should contain the flink-ml jar and all of its transitive dependencies.
Copying the library jars manually to the cluster
Flink includes all jars which are located in the <FLINK_ROOT_DIR>/lib folder in the classpath of the executed jobs. Thus, in order to use Flink's machine learning library you have to put the flink-ml jar and all needed transitive dependencies into the /lib folder. This is rather tricky, since you have to figure out which transitive dependencies are actually needed by your algorithm and, consequently, you will often end up copying all transitive dependencies.
How to build a specific sub-module with maven
In order to build a specific sub-module X from your parent project you can use the following command:
mvn clean package -pl X -am
-pl allows you to specify which sub-modules you want to build and -am tells maven to also build other required sub-modules. It is also described here.
In cluster mode, Flink does not put all library JAR files into the classpath of its workers. When executing the program locally in IntelliJ all required dependencies are in the classpath, but not when executing on a cluster.
You have two options:
copy the FlinkML Jar file into the lib folder of all Flink TaskManager
Build a fat Jar file for you application that includes the FLinkML dependencies.
See the Cluster Execution Documentation for details.

Spring boot application with apache axis

I am trying to run a spring boot jar which has axis2 dependencies in it. I am using spring boot maven plugin to build the jar (with dependencies). When I try to run my jar, I get the following exception in my console:
org.apache.axis2.AxisFault: The G:application\myapp\target\myapp.jar!\lib\axis2-1.6.1.jar file cannot be found.
at org.apache.axis2.deployment.repository.util.DeploymentFileData.setClassLoader(DeploymentFileData.java:111)
at org.apache.axis2.deployment.ModuleDeployer.deploy(ModuleDeployer.java:70)
at org.apache.axis2.deployment.repository.util.DeploymentFileData.deploy(DeploymentFileData.java:136)
at org.apache.axis2.deployment.DeploymentEngine.doDeploy(DeploymentEngine.java:813)
at org.apache.axis2.deployment.RepositoryListener.loadClassPathModules(RepositoryListener.java:222)
at org.apache.axis2.deployment.RepositoryListener.init2(RepositoryListener.java:71)
at org.apache.axis2.deployment.RepositoryListener.<init>(RepositoryListener.java:64)
at org.apache.axis2.deployment.DeploymentEngine.loadFromClassPath(DeploymentEngine.java:175)
at org.apache.axis2.deployment.FileSystemConfigurator.getAxisConfiguration(FileSystemConfigurator.java:135)
at ...
I then checked the structure of my jar. It has lib folder inside it, which contained all the jars (including the above mentioned axis jar). Attached is the screen shot of lib folder.
Following are the solutions which I have tried:
Placed axis jar in the same directory as application jar.
Created lib folder in the same directory as application jar and placed axis jar inside it.
Modified manifest file to include Class-Path: /lib/
None of the solutions has worked. However, when I run the application class in eclipse, the app starts and runs perfectly. But, once I create the jar, nothing seems to run.
Can anyone please help? Thanks in advance.
It looks like Axis can't cope with being run from a jar that's nested within another jar. It works fine in Eclipse as the Axis jar is available directly on the filesystem rather than being nested inside your Spring Boot application's jar file.
You can configure your application's fat jar file so that Spring Boot knows to unpack the Axis jar into a temporary location when it's run. If you're using Maven:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<requiresUnpack>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2</artifactId>
</dependency>
</requiresUnpack>
</configuration>
</plugin>
</plugins>
</build>
And if you're using Gradle:
springBoot {
requiresUnpack = ['org.apache.axis2:axis2']
}
See the Spring Boot documentation for some further details.

One Spring Boot project, deploy to both JAR or WAR

Is there a way to have a single Spring Boot project be packagable into both JAR and WAR without changing the pom.xml or the application source?
I've read Converting a Spring Boot JAR Application to a WAR, but it converts the project to WAR and it loses the ability to be packaged as JAR.
I don't expect mvn package to do both. What I want is something like mvn i-want-a-jar and it would package the project as JAR. Or I could run mvn i-want-a-war and it would package the project as WAR.
Is this possible?
I managed to do it by adding
<packaging>${packaging.type}</packaging>
to the POM file and then setting different profiles for JAR and WAR:
<profiles>
<profile>
<id>jar</id>
<properties>
<packaging.type>jar</packaging.type>
</properties>
</profile>
<profile>
<id>war</id>
<properties>
<packaging.type>war</packaging.type>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
</profiles>
Now mvn package -P war produces a WAR and mvn package -P jar produces a JAR.
Another option is to create separate modules for JAR and WAR, but I didn't go that route.
What's wrong with a WAR file that's executable? Isn't that what you really need?
P.S. like
java -jar name.war
We've recently had a similar requirement, where an existing Spring Boot based project that was originally packaged as an executable Jar needed to support Tomcat and WildFly deployments.
Due to some dependencies used in this project (for example WebJars), a simple switch to WAR package wasn't an option since some of those dependencies were required for WildFly (VFS support) but not for other deployment.
The solution was to restructure the project modules in a way that core module contained the actual project but without having Spring Boot’s plugin applied, while several package modules would depend on core module and configure deployment artifact specifics (Boot and other plugins, deployment specific dependencies etc.).
That way project build was able to generate multiple deployment artifacts (Boot's executable JAR, traditional WAR and WildFly specific WAR) in a single build run.
In case anyone finds this useful, the sample project to demonstrate the approach is available on Github. The project can be built by either Gradle or Maven.

Resources