How to compile and run Java application within Maven project in Eclipse? - java

I have an existing web application, A, which is a Maven project in Eclipse. It is run on a Tomcat 8 localhost server. Now I have a Java application, B, that was a separate project on its own. I have imported B into my workspace with A as another project. I am trying to run a main class (called App.java) which exists in B from a class within A. The class within A is below:
public void runOrgReportUtility() throws IOException {
int k = runProcess("javac /Users/ag/utilities/org-report-utility/src/main/java/com/vs/orgreport/App.java", null);
if (k==0) {
log.info("Compiled. Now trying to run class.");
String commandStr = "java -cp /Users/ag/utilities/org-report-utility/src/main/java/com/vs/orgreport/ App";
log.info("Command String: ");
log.info(commandStr);
runProcess(commandStr);
}
public int runProcess(String command, String[]) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
pro.waitFor();
return pro.exitValue();
}
When I tried running A, the console gave me a bunch of error: cannot find symbol, for various classes within B. This made me realize that only the App.java was being compiled and run, and not the other dependent classes in B.
How can my second java application be compiled and run when I start up my original web application?
Things I have tried:
Set (original) project references to include secondary Java app
Add Java app project to Java build path (in Projects tab) of original project
Added Java app to Deployment Assembly of original project

Do not compile the application when you want to call it. This is bad:
Compiling with javac is hard due to all the dependencies. As you found out, it is not a simple matter of invoking javac on a single java file.
Why wait until you try to run it to find out that you have an error that keeps it from compiling?
Why incur the overhead of compiling it every time you run it?
You normally would use maven to compile B and probably use the maven-shade-plugin to create a B.jar that contains B and all dependencies (aka a "fat" jar). Then when A invokes B, you can use the fat jar as the classpath when you invoke the app that it contains.
Other things you might consider:
You could probably also include the fat jar in your web application so that you are not dependent on having an external jar that must be in place in order for your web application to be fully functional.
Rather than execute the other application in a separate process, run it in the same JVM by just calling App.main() directly. You might want it to run in a separate thread, which is easy to do.
If you really want a separate OS process, use ProcessBuilder rather than Runtime.exec. In many cases, it is an easier API to use and get right.

Related

How does one compile and run a standalone executable JAR so that it can invoke Maven to run the parallel tests set up by Cucumber-JVM-parallel-plugin?

I am trying to execute parallel tests through the use of Maven InvocationRequest, Invoker, and InvocationResult components which are a part of maven-invoker dependency added into the pom.
Ultimately, I want Jenkins to run an executable jar which in turn executes the parallel tests. The code to programmatically invoke Maven to run the tests looks like this:
InvocationRequest request = new DefaultInvocationRequest();
request.setPomFile( new File("pom.xml") ); //pom is in the root level of the project
request.setShowErrors(true);
List<String> goalList = Arrays.asList("clean","install");
request.setGoals( goalList );
Invoker invoker = new DefaultInvoker();
invoker.setMavenHome(new File(System.getenv("MAVEN_HOME")));
InvocationResult result = null;
try {
result = invoker.execute( request );
} catch (MavenInvocationException e) {
e.printStackTrace();
}
if ( result.getExitCode() != 0 )
{
throw new IllegalStateException( "Build failed." );
}
This code lives in the main class (i.e., public static void main(String[] args) ) which serves as the entry point when running the compiled executable JAR. The idea is that Jenkins will fire off something akin to this -->> "java -jar MyCompiledTests.jar" ... and this would run the code above which allows the tests to run in parallel.
This works so long as I use the pom location where the original project files reside. But, I am needing to compile a JAR which will live on an integration server and would be run by Jenkins daily (I do this with the current battery of tests but currently they all run in series). It seems that when I build the executable JAR (using maven-assembly-plugin), the pom file is not added to it.
So, the code above which needs to access the pom will return an error saying it cannot find the pom. To remedy that, I manually added the pom file to sit alongside the JAR in the given remote folder, but then when running this arrangement, I receive an error concerning the absence of the Features folder.
This error happens when the Cucumber-JVM-parallel plugin is reached during pom execution. Receiving this error stems from the fact that the pom file is now being read but the various path references within this plugin are not recognized because they are relative to the location of the original project folders in Eclipse and not the new remote folder location alongside the executable JAR.
Again, I can run things in Eclipse just fine and can even run the compiled executable JAR as long as I can point to the pom file which lives at the original project folder.
The Question:
How does one compile and run a standalone executable JAR so that it
can invoke Maven to run the parallel tests set up by
Cucumber-JVM-parallel-plugin?
How should the pom be referenced in the code above differently?
Can the pom be wrapped into the executable JAR when it is compiled...or should it be?
Is there a more elegant way to compile and run the executable JAR
I have searched far and wide, but either I am not seeing the answer right in front of me, or my intended goals for this executable JAR are unachievable given the current state of maven technologies.

Java 9 migration on intellij issues with module system

I am try to migrate my current project to be able to compile and run it on java 9. I am trying first to just move a java8 based project to java9 without not much effort which means not moving to jigsaw basically.
The project structure is something like
myjava-service [myjava-service-parent] parent-pom with the following modules
- myjava-service
- myjava-service-common
- myjava-service-test
it compiles perfectly with mvn clean package and it runs when I execute that fat.jar
the nightmare starts when I try to run it using intellij,to run on intellij i have to set the module I want to execute which is myjava-service but then apparently intellij understand it as java 9 module and well a lot of split packages issues, classes not found and other issues that I am struggling to fix, so my question is there a way to run the service on intellij under the java 9 environment without the new java module system being triggered somehow?
for the record issues like
java.lang.module.ResolutionException: Modules javax.annotation.api and annotations export package javax.annotation to module javax.el
So, apparently someone stepped into the same issue that I was facing, so what happens is that when your service start by a class which is not part of your sources (in my case my service is started by Starter class from the Vertx jar) then IDEA end up using the module path instead of class path. luckily Intellij team was quite helpful, follow up the ticket
https://youtrack.jetbrains.com/issue/IDEA-187390 , for the next version IDEA will abstain from using module path when there is no module-info file in sources.
Also for those who need desperately run a service in java 9 there's a work around which is basically create a Main class and Invoke it inside the class that starts your service, in my Case it looked like
public class Start {
public static void main(String[] args) {
Starter.main(args);
}
}

Getting ClassNotFound Exception for class MkActivityMethod

I am trying to use JackRabbit lbrary for SVN chekin operation.
What I run my code through individual program this works fine. But when I run using web based project it doesn't work.
Code compiles fine but gives me runtime exception at following line :
MkActivityMethod activityMethod = new MkActivityMethod(url);
The exception is :
java.lang.NoClassDefFoundError: org/apache/jackrabbit/webdav/client/methods/MkActivityMethod
My project has jackrabbit-standalone-2.6.4.jar included in my eclipse jars as well as in project web-Inf/lib folder
Please let me know where I am going wrong.
There is obviously something wrong with your classpath. What Web Server Are You Using?
Here is my solution :
Try to build the project once again
Check the JDK version for the builder and Server JRE
Try clean the project (In eclipse , Project menu -> Clean )
Reason :
After you compile your code, you end up with .class files for each class in your program. These binary files are the bytecode that Java interprets to execute your program. The NoClassDefFoundError indicates that the classloader, which is responsible for dynamically loading classes, cannot find the .class file for the class that you're trying to use. It probably indicates that you haven't set the classpath option when executing your code. This link explains how to set the classpath when you execute.

Exporting Scala project as jar from Eclipse

I have a Scala project and I would like to export it as a jar.
*1. At first I tried creating a Java class for the project as an entry point
public class JMain {
public static void main(String[] args) {
System.out.println("Java main calling Scala main");
SMain.main(new String[] {""}); //SMain.main is the actual *main*
and this worked fine and dandy when launched from Eclipse, but when I export it as jar it'll give me 18 exceptions or so. I do now know how to replicate then "environment" in which Eclipse manages to launch this and I'm prety sure it relies on the fact that Scala is on my system already - I need a self contained jar with everything packed in there.
*2. My second try consisted of trying what lach suggested here How to deploy a Scala project from Eclipse?
namely:
public class JMain {
public static void main(String[] args) {
System.out.println("Java Main");
List<String> argList = new ArrayList<String>();
argList.add("fully.qualified.ClassName"); //???
for (String s : args) argList.add(s);
scala.tools.nsc.MainGenericRunner.main(argList.toArray(new String[0]));
This time it won't even run from Eclipse, although it gives only 6 or so exceptions starting with the famous NoClassDefFoundError. I have a feeling I'm not getting fully.qualified.ClassName right. *3. If the main Scala class is called "Dis.scala" and is located in package "pack" shouldn't this fully.qualified.ClassName be "pack.Dis"?
I'm using Jre 1.6 and Scala 2.9.2
EDIT: I have included all external imported jars, even scala-library.jar - everything is nice and packed in the jar
P.S. I am not familiar with Ant or Maven or Sbt. I just want my Scala project jared - if possible without getting into hairy things.
Here is what worked for me:
1. Create scala project
2. Create Wrapper java project
3. Add the scala-library.jar to you java project build path.
So you only need the 3rd step in addition since the rest looks similar to what I did. Then you can happily use: java - jar file.jar
EDIT:
How to create a JAR File which contains Scala/Code which can be consumed by another Java Project, using Scala - Eclipse IDE.
Create a new Scala Project and define an object with a main method as entry point.
Now create a new Java Project and add your Scala Project to the new ones buildpath. Additionally add the scala-library.jar to the Java project.
Now create a Wrapper class in the java project which calls your entry point class from the scala lib. Run the wrapper class to create a eclipse run configuration and test if you can call the scala project.
Use the Export->Java->Runnable JAR file, Wizard now on the wrapper project.The eclipse run configuration will be used as entrypoint into the JAR. Depending on your needs you may want to :
extract required libraries into generated JAR
or
Package required libraries into generated JAR
Finally you get a complete packaged JAR which you can use like this:
java - jar wrapped.jar
For me, it was relatively straightforward.
Develop and test the project using the scala IDE (or eclipse for java).
once ready, generate the jar for the project using file -> export method.
for submitting the spark (i was writing something for spark), i just had to mention --class option for specifying the main class for the jar.
hope to help.

Clojure and Java source in the same NetBeans project

Has anyone successfully created a NetBeans project that combines Clojure and Java source?
I have projects where the driver program (startup, gui, user prefs, etc.) are in Java, but the logic is in Clojure. At the moment, I compile the Clojure code to a jar in one project and import it as a library in a separate Java project. It would be convenient if all the source could be combined in one single NetBeans project.
Has anyone come up with a method to do this?
One possible solution is to modify your NetBeans Java project's Ant script (build.xml in your root directory) to have it .
By default, NetBeans creates several placeholder Ant targets in the root project directory's build.xml for you to override to automate tasks beyond the standard build process (such as compiling other languages to use their libraries in your current project). By overriding one of the placeholder targets in that build script such as "-pre-compile" you could write a simple target to call the Clojure compilation process using the Ant "exec" task and place all the resulting class files (or JAR) in the appropriate build directory.
If you do this frequently, you could define an Ant extension (via a macro or Ant plugin) so you don't have to modify the build.xml each time.
I use the RT method. I put my Clojure code into a script file that I include and process at startup:
try {
RT.loadResourceScript("com/mydomain/app/clojure_scripts.clj"); // Initialize Clojure script processor with our script
} catch (Exception e) {
Util.logException(e, "Unable to run Clojure initialization script.");
}
Then, since my main logic is in Java and I'm only calling out to Clojure for calculations, I use some glue code to map the calls for me:
/*
* Class to wrap Clojure scripts with Java friendly methods.
*/
public class Clojure {
private static final String ns="com.mydomain.app";
public static double calculate(final double size, final double otherVar) {
Var report=RT.var(ns, "calculate");
return (Double) report.invoke(size, otherVar);
}
};

Categories