Creating jars with multiple main classes in netbeans - java

I'm am creating a VoIP client server pair in java using the netbeans IDE. I would like to use only 1 project but I am unfamiliar with with how netbeans would create the Jar file. I need a to if this is possible and if so, how to set it up.

The JAR File Specification allows only one Main-Class attribute per JAR, but the JAR may have an arbitrary number of classes that declare a main() method. Any such class will be included in the project's Build Packaging property, unless specifically excluded.
As a concrete example, H2 Database includes these classes with main():
org.h2.jdbcx.JdbcConnectionPool
org.h2.tools.Backup
org.h2.tools.ChangeFileEncryption
org.h2.tools.Console
org.h2.tools.ConvertTraceFile
org.h2.tools.ConvertTraceFile
org.h2.tools.CreateCluster
org.h2.tools.DeleteDbFiles
org.h2.tools.Recover
org.h2.tools.Restore
org.h2.tools.RunScript
org.h2.tools.Script
org.h2.tools.Server
org.h2.tools.Shell
Addendum: Apparently, my junk-drawer project needs maintenance.
$ find scratch/src -name \*java | xargs -J % egrep 'main[ \t]*\(Str' % | wc -l
109

I don't know how Netbeans work, but it should be no problem putting more than one main class in a JAR. Actually a main class is just a class having a main method and a JAR is a collection of class files.
The only restriction is that there can only be one class that will be started with double-clicking the JAR.
To start the each class you must not use the -jar option, but provide the full class name.
For example, if you have a Client and a Server class in your JAR, the Client is started by
java -cp file.jar Client
and the Server by
java -cp file.jar Server.
An option is to create a third starter class used to start either the server or the client based on a command line argument (or a GUI window).

I believe the purpose of a 'main class' means that the eventual JAR' manifest file, will label one class as being the 'class to run': so that the end-user can just double-click it* or run a simplified commandline like:
java -jar <jar>
rather than having to specify the whole package/class name like:
java -cp <jar> com.yourcom.package.classname
If I'm right, then I don't see how it would make sense to have more than one main class ?
Maybe I misunderstod your question - or there is another purpose to the 'main' class?
If you mean having two classes which have a 'main' method - then this is fine - the end user can launch any of the classes by name - and so long as they have the standard main method sig, for instance:
public static void main(String[] args)
it should just work.
*(on Windows at least, and whether that works also depends on which JRE they have and probably other things)

In netbeans, if you want to create jar file of your project with your selected main class then ,
1. right click on your project (If you couldn't find your project then go to window -> Project from netbeans menubar )
2. Go to set configuration -> Customize.
3. Select run from categories, In main class write your packagename.classname (ie you have created file xyz in mypackage, then write mypackage.xyz)
4. click ok.
5. Again right click on projectname, select clean and build.
6. Your jar file is created at location of your projectname -> dist -> projectname.jar

Related

Maven project execution command

Below is my sample class file:
package org.foo.tutorial;
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}
In order to execute the project (maven framework) we run:
>java -cp Something-1.0.SNAPSHOT.jar org.foo.tutorial.APP
The above command works fine and gives me the output 'HELLO WORLD'.
However, if I leave out the third argument in the above command (org.foo.tutorial.APP) I get the following error:
Error: Could not find or load main class target.MavenTutorialApp-1.0-SNAPSHOT.jar
My question is:
Why should the groupId and app name matter when I am supplying the entire 'jar' file ?
The error is a bit misleading. Your java command is incorrect since you don't specify a class. The Something-1.0.SNAPSHOT.jar is meant to be part of the -cp option but java is interpreting it as the class.
That's how java behaves
The java command starts a Java application. It does this by starting a
Java runtime environment, loading a specified class, and calling that
class's main method.
If your .jar file contains an entry point specified by a Main-Class header in the manifest, then you can simply run
java -jar Something-1.0.SNAPSHOT.jar
Let me try to answer your question.
Why should the groupId and app name matter when I am supplying the
entire 'jar' file ?
Lets divide the question into smaller part -
What is group id? - The id of the project's group.
What is artifactId? - The id of the artifact (project) and off course version is part of default artifact name.
While running a java program under jvm there are no such effect that how you built jar, for example it is produced by maven or gradle build process or even command line.
Things that matter is jar file and entry point or the class where main reside.
This may be out of scope of this question, but i felt relevant.
To run java program from jar file, you can explicitly mention like above. Also you can create executable jar file by adding manifest file, where it define the entry point of the executable -
Main-Class: org.foo.tutorial.APP
How to create executable jar?
Also maven maven-assembly-plugin helps to package executable jar.
help

Error; Could not find or load main class (Java using Windows CMD)

I am trying to compile and run some java files I have made in Eclipse. The full path to the .java file is C:\Users\MYNAME\Documents\Java\Introduction\src\tests\Test.java. tests is the package I created in Eclipse and src is a folder that Eclipse made under Introduction (which is the project name).
In my environment variables, I have the following relevant variable:
JAVA_HOME C:\Program Files (x86)\Java\jdk1.7.0_40\bin
Under system variables I have the following:
CLASSPATH %JAVA_HOME%
I go to my cmd and cd into the tests directory (cd C:\Users\MYNAME\Documents\Java\Introduction\src\tests). Then I compile using javac Test.java. This seems to work as I then have a Test.class file under the same directory. Now I want to run the file, I type java Test and I get the error, "could not find or load main class". I've tried a variety of things including appending .class and .java to the end but I keep getting the error. I looked at some answers and docs and I managed to get it to work if I cd into:
cd C:\Users\MYNAME\Documents\Java\Introduction\src (i.e, get out of the package)
and then run:
java -cp . tests.Test
So that seems to temporarily set the class path to the current directory, and run Test from the package tests. However, I want to simply be able to type java Test. I know it's possible as I used to be able to do it, but now for some reason I cannot (I must have changed something along the way...).
Any help is appreciated.
However, I want to simply be able to type java Test
That will only work if Test is in the default package - it's as simple as that. You need to pass the java executable the fully-qualified name of the class you want to launch. There's no way round that.
Of course, you could create your own launcher which looks in the current directory for class files, finds out the fully-qualified name of the classes within those files, and launches java providing the full name and probably specifying an appropriate classpath... but that seems like a lot of hassle compared with just including the package name in the command.
You could be making the same mistake I made. So, try the following.
Here is my code for your reference.
class A{
public static void main(String args[]) {
System.out.println("Hello world");
}
}
Once you saved this as "C:\JavaStudy\ClassA.java", try the following.
c:\JavaStudy>javac ClassA.java
c:\JavaStudy>java A.class
Error: Could not find or load main class A.class
c:\JavaStudy>java A
Hello world
c:\JavaStudy>
Note: You don't need to use " java.exe -cp . " if you have class file in the same directory from where you are executing.

Can a .jar file to be exexcuted under Windows have more than one main method?

we have a big project with many classes (~100) and in some there are main methods.
Building a runnable .jar-File to be executed under a WinXP environment fails; we have the idea that maybe it is because there is not only one but many main-methods in our project?!
So I read some about it and as fas as I got it, a .jar can contain more than 1 main-method; they would be called like this:
java -classpath myJarFile.jar A
java -classpath myJarFile.jar B
java -classpath myJarFile.jar C
where A,B and C have their own main methods (see http://www.coderanch.com/t/373658/java/java/Executing-main-methods-jar-file)
My question is: Does having more than one main method affect the problem-free running on Windows ?
Thanks in advance!
You've said you're making a runnable jar file, but your examples (java -classpath myJarFile.jar A) aren't using it as a runnable jar; they're just using it as a jar. You're specifying what class to run on the java command-line. That should work just fine.
Re runnable jars: The point of runnable jars is that you don't have to start them with the java command directly; you just double-click the jar in a file explorer, make it the target of a shortcut, etc., and the java tool is run automatically (via file association), using the jar's startup class, which is specified in the manifest you used when creating the runnable jar:
Manifest-Version: 1.0
Main-Class: Startup
In that example, Startup is the startup class for the runnable jar.
You could make the jar a runnable jar (e.g., pick a default class to run the main from and make it the startup) and still allow the jar to be run via the java tool choosing another class. That's fine.
No - the main method is just the entry point for the program.
For executing the application Main method is just like door for entire application. But you can add some other class as well which is have there individual main methods but entry main method should all ways be one.
No, it's not a problem if you are able to control the invocation of your program (as opposed to this being a dropin/plugin, for example).
Does having more than one main method affect the problem-free running on Windows ?
It will if you try to do java -jar myJarFile.jar. The jar manifest allows you to optionally specify no more than one main class.
If you want have multiple main methods you need to use following syntax only
java -classpath myJarFile.jar A

Java: simple JAR project, when run, cannot find an imported class in a second simple JAR project even though second JAR passed via -classpath

I have written two simple Java classes (one of them containing "main()", and the other called by "main()").
Class #1 (containing "main()"):
package daniel347x.outerjar;
import daniel347x.innerjar.Funky;
public class App
{
public static void main( String[] args )
{
Funky.foo();
}
}
Class #2 (called by "main()"):
package daniel347x.innerjar;
public class Funky
{
public static void foo()
{
System.out.println( "Funky!" );
}
}
The above classes appear in different project root folders, and use Maven as the build system (each project has its own POM). The pom.xml file for the main project includes the proper entry to add daniel347x.outerjar.App as the main class, and it properly includes the dependency on daniel347x.innerjar. Both projects build successfully into JAR files.
I use NetBeans to wrap these as Maven projects (in fact, I used NetBeans to create both projects). When I run the main project from within NetBeans, it runs successfully and I see Funky! as the output.
However, when I attempt to run the main class straight from the Windows command line (cmd.exe), passing the JAR file containing Funky on the command line's classpath, as such:
java -classpath "P:\_Dan\work\JavaProjects\JarFuckup\innerjar\target\innerjar-1.0-SNAPSHOT.jar" -jar "P:\_Dan\work\JavaProjects\JarFuckup\outerjar\target\outerjar-1.0-SNAPSHOT.jar"
... I receive the dreaded NoClassDefFoundError:
Exception in thread "main" java.lang.NoClassDefFoundError: daniel347x/innerjar/Funky
at daniel347x.outerjar.App.main(App.java:7)
I have carefully confirmed that, inside the innerjar JAR file noted above containing Funky, that the path structure is daniel347x\innerjar and that inside the innerjar folder is the Funky.class file - and this file looks correct within a HEX editor where I can see the ASCII strings representing the name of the class.
The fact that the class can't be found defies my understanding of Java, which I thought allows you to pass JAR files as a -classpath parameter and it will be able to find classes inside those JAR files.
This very basic point has me flummoxed - an answer that explains what I am doing wrong would be greatly appreciated.
The classpath is ignored when using the -jar option. A way to run your app would be java -classpath "P:\_Dan\work\JavaProjects\JarFuckup\innerjar\target\innerjar-1.0-SNAPSHOT.jar";"P:\_Dan\work\JavaProjects\JarFuckup\outerjar\target\outerjar-1.0-SNAPSHOT.jar" daniel347x.outerjar.App
Perhaps a better approach would be to add a manifest file to the Jar that specifies the class path of the dependent Jars by relative paths. Then..
java -jar "P:\_Dan\...\outerjar-1.0-SNAPSHOT.jar"
..should do it.
Double clicking the main Jar will also launch it. That is mostly useful for GUIs.

How do I run .class files on windows from command line?

I'm trying to run .class file from command line. It works when I manually move to the directory it's stored in, but when I try something like this:
java C:\Peter\Michael\Lazarus\Main
it says it can't find the main class. Is there any solution to this other than making a .jar file (I know that .jar is the best solution, but at this moment isn't the one I'm looking for)?
The Java application launcher (a.k.a java.exe or simply java) supports up to four different ways to specify what to launch (depending on which Java version you use).
Specifying a class name is the most basic way. Note that the class name is different from the file name.
java -cp path/to/classFiles/ mypackage.Main
Here we start the class mypackage.Main and use the -cp switch to specify the classpath which is used to find the class (the full path to the class mypackage.Main will be path/to/classFiles/mypackage/Main.class.
Starting a jar file.
java -jar myJar.jar
This puts the jar itself and anything specified on its Class-Path entry on the class path and starts the class indicated via the Main-Class entry. Note that in this case you can not specify any additional class path entries (they will be silently ignored).
Java 9 introduced modules and with that it introduce a way to launch a specific module in a way similar to how option #2 works (either by starting that modules dedicated main class or by starting a user-specified class within that module):
java --module my.module
Java 11 introduces support for Single-File Source Code Programs, which makes it very easy to execute Java programs that fit into a single source file. It even does the compile step for you:
java MyMain.java
This option can be useful for experimenting with Java for the first time, but quickly reaches its limits as it will not allow you to access classes that are defined in another source file (unless you compile them separately and put them on the classpath, which defeats the ease of use of this method and means you should probably switch back to option #1 in that case).
This feature was developed as JEP 330 and is still sometimes referred to as such.
For your specific case you'd use option #1 and tell java where to look for that class by using the -classpath option (or its short form -cp):
java -classpath C:\Peter\Michael\Lazarus\ Main
If your Main.java contains the entirety of your source code (and it is in the same directory), then you can use option #4, skip the compile step and directly compile-and-execute it:
java c:\Peter\Michael\Lazarus\Main.java
Assuming that Main.class does not have a package declaration:
java -cp C:\Peter\Michael\Lazarus\ Main
Java looks for classes in a "classpath", which can be set on the command line via the -cp option.
I just had the same issue, I tried running java hello.class, this is wrong.
The command should be java hello.
Do not include the file extension. It is looking for a class file, and will add the name on its own.
So running 'java hello.class' will tell it to go looking for 'hello.class.class' file.
Try this:
java -cp C:\Peter\Michael\Lazarus Main
You need to define the classpath.

Categories

Resources