How to make an executable JAR files - netbeans

How do you build an executable JAR file in Netbeans 12.6? I realize this question is asked frequently but none of the other solutions previously posted here work on the latest version of Netbeans. All I ever get is "no main manifest attribute". Amazing to me that such a simple thing does not just work out-of-the-box. Getting Netbeans set up has been harder to learn than Java itself!

When you set the project’s main class, you ensure that the main class is be designated in the manifest. To set the project’s main class:
Right-click the project’s node and choose Properties.
Select the Run category and enter projectname.className in the Main Class field.
Click OK to close the Project Properties dialog box.
https://netbeans.apache.org/kb/docs/java/javase-deploy.html

Here is what worked for me. For Maven, you need to update the POM.xml file. Netbeans does not work out of the box in version 12.6 like older versions. I'm sure they added more functionality but it no longer just works. It maybe similar for Gradle. Add this above ~ < /project> in your file. Change your class name to your's. (My class was called main).
<build>
<plugins>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.mypackage.MyClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>

Related

How to disable derived flag on generated source code from Mapstruct and how to generate Mapstruct classes only on local PC and not on build server?

First question: Mapstruct generates code to target annotation folder which has a marker "derived". This is ignored by RTC so I'm unable to check in the generated code (don't ask me why I want to do this - I need it). Is there any chance to disable derived marker on gen-folder so generated classes (.java) could be checked into repository?
Second question: Mapstruct classes should be generated on my local machine and not on a build server. How can I configure maven to do it only local?
Thank you in advance.
Currently my pom.xml looks like this since I was not able to configure it the way I need it:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<generatedSourcesDirectory>gen</generatedSourcesDirectory>
<annotationProcessorPaths>
<path>
<groupId>de.......</groupId>
<artifactId>mapstruct_config</artifactId>
<version>${config.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<compilerArg>
-Amapstruct.suppressGeneratorTimestamp=true
</compilerArg>
<compilerArg>
-Amapstruct.suppressGeneratorVersionInfoComment=true
</compilerArg>
<compilerArg>
-Amapstruct.unmappedTargetPolicy=WARN
</compilerArg>
</compilerArgs>
</configuration>
</plugin>
1: gen folder has no derived marker
2: annotationProcessor works only on a local machine
I presume that the dervied marker comes from Eclipse (IntelliJ also does that). Most probably you would have to manually disable that in your IDE, not sure if it will always work as usually those locations are applied from Maven itself.
In order for the Annotation Processor to run only locally I think that you would need to add a custom maven profile where you would configure the annotationProcessorPaths, the default one (on the CI) won't have the annotationProcessorPaths and thus won't run the annotation processing

Eclipse, Maven and incorrect MANIFEST.MF file being used

This time I have a problem with running my Web App project in Eclipse.
Whenever I'll commit my app to SVN, then build it and deploy using Jenkins to Tomcat container - the app runs fine, and the correct MANIFEST.MF is used.
But, when I want to debug it inside Eclipse (with Tomcat 8.5 container) - there is an deafult manifest file used instead of the one containing my custom properties from pom.xml.
I've defined few variables in pom.xml regarding the application name, version and so on. The manifest file is being generated in /target/generated-resources/m2e-wtp/webResources/META-INF/MANIFEST.MF. This file contain all of my custom properties.
But when I call
resources = getClass().getClassLoader()
.getResources("META-INF/MANIFEST.MF");
The path returned is: /META-INF/MANIFEST.MF. The file indeed exists, but is almost empty:
Manifest-Version: 1.0
Class-Path:
Here's my pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<!-- Exclude an unnecessary file generated by the GWT compiler. -->
<!-- <packagingExcludes>WEB-INF/classes/VAADIN/widgetsets/WEB-INF/**</packagingExcludes>-->
<manifest>
<addClasspath>true</addClasspath>
<addDefaultImplementationEntries>false</addDefaultImplementationEntries>
</manifest>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
<manifestEntries>
<Specification-Title>${project.name}</Specification-Title>
<Specification-Version>${project.version}</Specification-Version>
<App-Version>${build.version}</App-Version>
<Build-Number>${build.number}</Build-Number>
<SVN-Revision>${rev.number}</SVN-Revision>
<Sys-Name>${sys.name}</Sys-Name>
<Sys-Full-Name>${sys.full.name}</Sys-Full-Name>
</manifestEntries>
</archive>
<!-- <packagingExcludes>WEB-INF/classes/META-INF/MANIFEST.MF</packagingExcludes> -->
</configuration>
</plugin>
I've tried almost every suggestion I've googled so far and nothing works :(
Please help!
Thank you in advance
Tom
Okay,
Finally I've found a solution. It turned out that I just need to simply copy a generated MANIFEST.MF file from the genrated wtp output folder to my project META-INF.
During building on Jenkins - the file is getting ovewritten by the generated one anyway so it seems that this makes no harm to project.

How does gwt hosted mode observe changes?

I am running gwt hosted mode through a proxy; debugging works, but it doesn't pick up changes to client code made in my IDE.
I am using the maven plugin to start hosted mode; configuration is as follows. The reason that webapp code is in /web is that the app is based on dropwizard, which can't server web assets out of root; thus I have src/main/webapp/web/* as my web assets.
So what's wrong with this maven config?
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<webappDirectory>${project.build.outputDirectory}/web</webappDirectory>
<hostedWebapp>${project.build.outputDirectory}/web</hostedWebapp>
<!--<copyWebapp>true</copyWebapp>-->
<module>com.flavor8.todo</module>
<runTarget>index.htm</runTarget>
<persistentunitcache>false</persistentunitcache>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test</goal>
<goal>resources</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>2.5.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-dev</artifactId>
<version>2.5.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-servlet</artifactId>
<version>2.5.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
</plugin>
Multi-step answer, starting with the answer to the title, then explaining why your app isn't behaving:
When a GWT app is being debugged in Dev Mode, the page starts up the hosted.html file, which connects to the browser plugin, which then tries to read the code server running at (by default) localhost:9997. When that connection is made, dev mode finds the module file, and gets things going. A custom classloader, 'CompilingClassLoader' is used by dev mode to do the other work that is required:
At startup, all JavaScriptObject classes need to be found and merged into one giant type, JavaScriptObject$, so that you can freely cast from one JSO to another, and invoke any JSO method on any other JSO. This JavaScriptObject$ type is synthesized at module start up.
When any class is requested, this custom class loader picks up classes as needed from the filesystem or from any jar. It compiles them on the fly from the .java file, hence the name. This is done both to get a new instance of the class with un-initialized static fields, but also to find all JSNI methods and correctly wire them up to call into the browser and back again. This wiring is why you can make changes to any file and simply refresh the browser - Dev Mode will always try to load the file from the filesystem fresh and create the actual Java class as needed.
The compiling classloader reads from your classpath - of course if it can't find a file, then that class cannot be used, and likewise if there is more than one copy of a file, then only the first copy found will be used...
The problem is the line
<goal>resources</goal>
Assuming you are working on a war project and not lib, this line doesn't need to be there.
This line copies not only the .class files to your target/classes directory, but also any other resources that a GWT library would need to have in its jar. Since you aren't writing a library but an application, this isn't necessary to do here, and in fact it is causing problems. On the dev mode classpath, target/classes is the first entry, followed by your source directories, then each jar on your classpath.
Either when you start the project or when you ask maven to compile it, this gwt:resources goal is run, and all sources are moved. Then later when you edit a file from your IDE, the IDE's own compiler updates the .class file in target/classes, but doesn't know what gwt:resources is for, so doesn't re-run it. This means that while target/classes has the latest .class files, it has out of date .java files.
If you need your source files to actually be in target/classes, either make sure that gwt:resources runs with every resource change in your IDE, or another way to copy sources directly to the target/classes directory is to set up a <resource> entry in your pom.

How can I run a Maven webapp in Eclipse when I need resource filtering for properties files?

I need to get some updates on this issue, I found this thread back in 2009 here, but the answer was to use maven 2, I'm not sure if Q4E works with maven 3 or not. I need to have some properties files filtered during the mvn package phase for the resulting war to be functional, the resource filtering is working fine with CLI mvn install. But when I do "Run on server/debug on server", the filtering is not working any more.
The aforementioned thread author ended up using q4e, claiming q4e gets the resource filtering right. I have q4e installed as well along with m2e, but still doesn't work, so I don't know if q4e is not working with maven 3, or I'm doing something wrong.
Thanks,
David
updated to the latest m2e-wtp plugin 0.15 (resource filtering bug fix since 0.12), it works fine now.
I'm not sure if this matches your problem, but I wanted to populate my web.xml file with properties from the pom during build and I put a groovy script in the pom to do it. It worked a treat and might work for you too. It definately works in both eclipse and on the command line. Here is my pom fragment:
<plugin>
<!-- Groovy script to set the description and version in the web.xml display name -->
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>groovy-magic</id>
<phase>prepare-package</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
def file = new File("src/main/webapp/WEB-INF/web.xml");
def fileText = file.text;
def match = "<display-name>[^<]*</display-name>";
def replace = "<display-name>"+project.description+" "+project.version+"</display-name>";
fileText = fileText.replaceAll(match, replace);
file.write(fileText);
println "Updated web.xml"
</source>
</configuration>
</execution>
</executions>
</plugin>

Requestfactory Validation on Multi-Project Setup

I tried changing to the release version of gwt2.4 and run into a problem. I use multiple projects in my setup. I have a project with serverside code, one project with shared code, that can be used in different gwt projects and a gwt project binding everything together. I build everything with maven. i followed the instructions for annotationprocessing found here:
http://code.google.com/p/google-web-toolkit/wiki/RequestFactoryInterfaceValidation
when I compile my shared project, where the proxies and services are, the folder "generated-sources\apt\" with the DeobfuscatorBuilder.java is created. I have the sources of this project as dependency of my mainproject and try to run the validator as well, but the DeobfuscatorBuilder.java is not created here. Everything compiles but when I invoke a call to the requestfactory I get the error:
com.google.web.bindery.requestfactory.server.UnexpectedException: No RequestContext for operation ZwI9iqZS626uTt_TFwRtUwPYSOE=
I guess there is an mistake in my setup, but I could't find where ..
Does anybody know how to solve this problem?
Regards
arne
UPDATE:
I added this to my pom:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>initialize</phase>
<goals>
<goal>unpack</goal>
<!-- <goal>build-classpath</goal> -->
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.myproject.core</groupId>
<artifactId>shared</artifactId>
<version>${shared.version}</version>
<classifier>sources</classifier>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/com.myproject.shared</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
This unpacks the sources of my dependencies and puts them into my target folder.
Then I added:
<configuration>
<sourceDirectory>target/com.fileee.shared</sourceDirectory>
</configuration>
to my processor-plugin.
This way it is not necessary to have all the projects in the workspace and it should work with a continous integration system. Wouldn't have figured that out without Andys reply though :)
I had the same issue and spent hours scouring the web for an answer without any luck. If I add the processor plugin to the shared project, it generates the DeobfuscatorBuilder class, but I get the same No RequestContext exception as you. If I just have the processsor plugin on the GWT war project, the builder isn't generated at all.
With a fair amount of trial and error I found adding the source directory from the shared project into the processor plugin configuration on the war project worked...
http://code.google.com/p/android-shuffle/source/browse/shuffle-app-engine/pom.xml#269
It's a bit dirty, but it does the trick. If there's an official method that doesn't require cross project hackery I'd be more than welcome to switch, but I haven't seen anything suggested yet.
Cheers
Andy