Unable to change Main-Class property within Manifest.mf - spring

I am upgrading a springboot app from 1.X to 2.1.3.RELEASE. My Springboot is a multi module project setup which is triggered using a java command something similar to this.
java -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5088 -Drun.jvmArguments="-Xdebug" -Dloader.path=C:\code\build\libs\dir\ -jar C:\code\build/libs/core.jar --spring.config.location=C:\config\application.properties
This is how the project structure looks like
App
Common
Core (has the main class)
Sub
Before the upgrade : Manifest.mf file of core.jar looks like this
Manifest-Version: 3.2.15.signature.LOCALDEV
Project-Name: core
Built-By: dkumar
Built-Date: 2020-11-10 16:09
Project-Version: 3.2.15.signature.LOCALDEV
Spring-Boot-Version: 1.5.1.RELEASE
Main-Class: org.springframework.boot.loader.PropertiesLauncher
Git-Branch: signature
Start-Class: com.demo.Main
Spring-Boot-Classes: BOOT-INF/classes/
Git-Commit-Hash: signature
Project-Group: com.demo.print
Spring-Boot-Lib: BOOT-INF/lib/
After the upgrade. This what the manifest.mf file looks like
Manifest-Version: 3.1.87.upgradespring.LOCALDEV
Git-Branch: upgradespring
Project-Name: core
Built-By: dkumar
Built-Date: 2020-11-18 18:15
Start-Class: com.demo.Main
Git-Commit-Hash: upgradespring
Project-Group: com.demo.print
Project-Version: 3.1.87.upgradespring.LOCALDEV
Main-Class: org.springframework.boot.loader.JarLauncher
Before the upgrade the following property in my Core build.gradle took care of using org.springframework.boot.loader.PropertiesLauncher which inturn used -Dloader.path to load all the Sub (subprojects) jars on to the classpath
springBoot{
mainClass = "com.demo.Main"
layout = "ZIP"
}
After the upgrade, the layout property is now deprecated in 2.1.3.RELEASE and the Main-Class is now changed to Main-Class: org.springframework.boot.loader.JarLauncherand this doesn't support the usage of -Dloader.path (I think). Because of this I always get No bean found error when i try to invoke a class of Sub (subproject). This happens because -Dloader.path fails to include the JARS from subproject onto the classpath. Before the upgrade I could see the relevant jars on the class path.
I tried several ways to change the Main-Class attribute within the manifest to use PropertiesLaucher but none seem to have worked. I have also looked at the plugin documentation and tried something similar but that to didn't work
https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/gradle-plugin/reference/html/#packaging-executable-configuring-properties-launcher
I think by changing the Main-class I can solve this problem but I am not sure how to do that.
Any suggestions or idea would be helpful. All comments are welcome. I will update the question if the need arises.
I apologize in advance as i am unable to place a larger code snippet due corporate policies.

I was able to resolve this by adding the following properties
bootJar {
manifest {
attributes(
'Main-Class': 'org.springframework.boot.loader.PropertiesLauncher',
'Spring-Boot-Classes': 'BOOT-INF/classes/',
'Spring-Boot-Lib': 'BOOT-INF/lib/'
)
}
}
Only this should work as well within the manifest:
'Main-Class': 'org.springframework.boot.loader.PropertiesLauncher'

Related

GMavenPlus: Groovy to JAR - Failed to find or load main class. Main class is present, manifest file appears valid

I've done a successfull mvn clean install on the project I built and the structure appears correct, all classes included and manifest is under META-INF including class-paths and main-class. Not sure what's not matching up here, but the class contents are valid when I checked contents using javap. Main method is present in the redacted_automatedSupport class and is also public.
Error:
host MINGW64 ~/Desktop/Projects/redacted_Automated_Support/target (master)
$ java -jar redacted_automatedSupport-1.0.jar
Error: Could not find or load main class support.redacted_automatedSupport
host MINGW64 ~/Desktop/Projects/redacted_Automated_Support/target (master)
$ java -cp redacted_automatedSupport-1.0.jar support.redacted_automatedSupport
Error: Could not find or load main class support.redacted_automatedSupport
host MINGW64 ~/Desktop/Projects/redacted_Automated_Support/target (master)
$
Manifest contents:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: bennet.vella
Class-Path: aws-java-sdk-s3-1.11.696.jar aws-java-sdk-kms-1.11.696.jar
aws-java-sdk-core-1.11.696.jar commons-logging-1.1.3.jar httpclient-
4.5.9.jar httpcore-4.4.11.jar commons-codec-1.11.jar ion-java-1.0.2.j
ar jackson-databind-2.6.7.3.jar jackson-annotations-2.6.0.jar jackson
-core-2.6.7.jar jackson-dataformat-cbor-2.6.7.jar joda-time-2.8.1.jar
jmespath-java-1.11.696.jar groovy-3.0.1.jar groovy-json-3.0.1.jar gr
oovy-dateutil-3.0.1.jar
Created-By: Apache Maven 3.6.3
Build-Jdk: 1.8.0_231
Main-Class: support.redacted_automatedSupport
Jar Archive Contents (renamed to zip to browse):
Support Jar Contents (removed some unecessary data, all names match):
It is not a complete answer, since it doesn't target the Maven issue I was having, but I did solve the IntelliJ problem I had with the wrong manifest file - and that's because I was creating the manifest in src/main/java when it should have been src/main/resources. This should hopefully alleviate some users' problems.
I have not however resolved how to properly build and include all relevant dependent jars using Maven - intelliJ does this successfully.

BitBucket Server Maven error: The default package '.' is not permitted by the Import-Package syntax

I am developing a plugin for BitBucket Server. Today, the Maven instance started throwing the following error after I changed the scope of one dependency:
[ERROR] Manifest com.my-plugin:integrationPlugin:atlassian-plugin:0.1-DEV : The default package '.' is not permitted by the Import-Package syntax.
This can be caused by compile errors in Eclipse because Eclipse creates
valid class files regardless of compile errors.
The following package(s) import from the default package null
[ERROR] Error(s) found in manifest configuration
After I reverted the change, the error did not go away.
I have tried solutions described in other StackOverflow posts, but they did not help me, since:
I am not using Eclipse
I have all packages declared in all my class files
The Bundle tool has this error fixed already
The manifest I got from the Maven debugging output is:
[DEBUG] Final Manifest:
#-----------------------------------------------------------------------
Manifest-Version: 1.0
Atlassian-Build-Date: 2019-04-04T11:44:27+0000
Atlassian-Plugin-Key: com.my-plugin.integrationPlugin
Bnd-LastModified: 1554378274635
Build-Jdk: 1.8.0_191
Built-By: egta136
Bundle-ClassPath: .,META-INF/lib/commons-logging-1.2.jar,META-INF/lib/pd
fbox-2.0.14.jar,META-INF/lib/fontbox-2.0.14.jar,META-INF/lib/ij-1.52n.j
ar
Bundle-Description: This is the com.my-plugin:integrationPlugin plu
gin for Atlassian Bitbucket Server.
Bundle-DocURL: https://example.com
Bundle-ManifestVersion: 2
Bundle-Name: integrationPlugin
Bundle-SymbolicName: com.my-plugin.integrationPlugin
Bundle-Vendor: Example
Bundle-Version: 0.1.0.DEV
Created-By: Apache Maven Bundle Plugin
Export-Package: com.my-plugin.integrationPlugin.api;version="0.1.0"
Import-Package:
com.apple.eawt;version=0;resolution:=optional,
com.atlassian.bitbucket.auth;version=0;resolution:=optional,
com.atlassian.bitbucket.commit;version=0;resolution:=optional,
com.atlassian.bitbucket.project;version=0;resolution:=optional,
com.atlassian.bitbucket.user;version=0;resolution:=optional,
com.atlassian.plugin.spring.scanner.annotation.export;version=0;resolut
ion:=optional,
com.atlassian.plugin.spring.scanner.annotation.imports;version=0;resolu
tion:=optional,
com.atlassian.sal.api;version=0;resolution:=optional,
com.atlassian.sal.api.pluginsettings;version=0;resolution:=optional,
com.atlassian.soy.renderer;version=0;resolution:=optional,
com.dizainsync.ddm.integrationPlugin.api;version=0;resolution:=optional
,
com.fasterxml.jackson.databind;version=0;resolution:=optional,
com.google.common.collect;version=0;resolution:=optional,
javax.crypto;version=0;resolution:=optional,
javax.crypto.spec;version=0;resolution:=optional,
javax.imageio;version=0;resolution:=optional,
javax.imageio.metadata;version=0;resolution:=optional,
javax.imageio.plugins.jpeg;version=0;resolution:=optional,
javax.imageio.stream;version=0;resolution:=optional,
javax.inject;version=0;resolution:=optional,
javax.script;version=0;resolution:=optional,
javax.servlet;version=0;resolution:=optional,
javax.servlet.http;version=0;resolution:=optional,
javax.swing;version=0;resolution:=optional,
javax.swing.event;version=0;resolution:=optional,
javax.swing.table;version=0;resolution:=optional,
javax.swing.text;version=0;resolution:=optional,
javax.swing.text.html;version=0;resolution:=optional,
javax.swing.tree;version=0;resolution:=optional,
javax.tools;version=0;resolution:=optional,
javax.xml.namespace;version=0;resolution:=optional,
javax.xml.parsers;version=0;resolution:=optional,
javax.xml.xpath;version=0;resolution:=optional,
org.apache.avalon.framework.logger;version=0;resolution:=optional,
org.apache.commons.fileupload;version=0;resolution:=optional,
org.apache.commons.fileupload.disk;version=0;resolution:=optional,
org.apache.commons.fileupload.servlet;version=0;resolution:=optional,
org.apache.commons.io;version=0;resolution:=optional,
org.apache.commons.lang3;version=0;resolution:=optional,
org.apache.log;version=0;resolution:=optional,
org.apache.log4j;version=0;resolution:=optional,
org.bouncycastle.asn1;version=0;resolution:=optional,
org.bouncycastle.asn1.cms;version=0;resolution:=optional,
org.bouncycastle.asn1.pkcs;version=0;resolution:=optional,
org.bouncycastle.asn1.x500;version=0;resolution:=optional,
org.bouncycastle.asn1.x509;version=0;resolution:=optional,
org.bouncycastle.cert;version=0;resolution:=optional,
org.bouncycastle.cms;version=0;resolution:=optional,
org.bouncycastle.cms.jcajce;version=0;resolution:=optional,
org.slf4j;version=0;resolution:=optional,
org.w3c.dom;version=0;resolution:=optional,
org.xml.sax;version=0;resolution:=optional,
com.atlassian.plugin.osgi.bridge.external
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
Spring-Context: *
Tool: Bnd-3.5.0.201709291849
#-----------------------------------------------------------------------
What could be causing this? It is especially weird since reverting the changes to pom.xml did not get rid of the error.
The error was caused by the ImageJ dependency that I had. Apparently some of their classes use the default package which does not play well with maven. Removing the dependency fixes the issue.
I had a similar issue. To find out which dependency may prevent OSGi packaging to work, review error message like Classes found in the wrong directory: {META-INF/versions/9/module-info.class=module-info}
Using jcfind to identify its origin, as an example:
./target/classes/META-INF/lib/classgraph-4.8.43.jar META-INF/versions/9/module-info.class
I am contacting parent POM provider to get this fixed.

Spring Tools Suite and Gradle - Setup to use correct resources from inside STS

I have a Spring Boot Gradle project setup in Spring Tools Suite (3.7.2 RELEASE) with the following source folders:
- src/integration-test/java
- src/integration-test/resources
- src/main/java
- src/main/resources
- src/test/java
- src/test/resources`
Whenever I run the application or unit tests from within STS, I see that STS is using the resources found under src/integration-test/resources.
I see a duplicate resource warning in STS for files which exist in all 3 resource source folders. For example, I have an application.properties in all 3 source folders and I see following:
The resource is a duplicate of src/integration-test/resources/application.properties and was not copied to the output folder
If I run the application as a JAR or unit tests/integration tests from the command line (via gradle build), everything seems to use the correct resources. This makes me believe it is a problem with how STS/Eclipse is handling gradle.
Does anybody know of how I can configure STS to use the correct resource source folders when using gradle?
I think my problem may be related to (or the same as?) Spring Boot incorrectly loads test configuration when running from eclipse+gradle, https://issuetracker.springsource.com/browse/STS-3882, https://issues.gradle.org/browse/GRADLE-1777
I also tried the solution found here, but that seems to only fix Maven builds:
Spring Tool Suite finds spring-boot integration test configuration and does not start main application
I think my problem may be related to...
Yes, it is related but in my opinion not the same. That problem is caused by the runtime classpath being incorrect. This problem is an error coming from the eclipse project builder so it is a compile-time issue.
The problems are closely related though. Depending on your point of view, you could say they are the same (incorrect mixing of test and compile-time classpaths).
Here, specifically, the problem is that the eclipse builder tries to copy all the resources it finds in source folders to the project's single output folder. Each source folder has a 'application.properties'. The builder warns that it could not copy some of them because one would overwrite the other.
I think there may be a solution for this problem. But it is a solution that really should come from Gradle + ( BuildShip | STS Gradle Tooling) than from you.
It is possible in Eclipse to configure each source-folder individually to target a specific outputfolder. Maven + M2E are doing this correcty, but Gradle + (BuildsShip | STS Gradle Tooling) combdos do not.
For example this is what maven puts into the eclipse .classpath file when it configures a test resources folder:
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
Notice how it explicitly sets the output folder for that entry (to something different from the project's default output folder).
You may be able to address the problem yourself by modifying the .classpath for a gradle project in a similar way. Either by doing it manually or from your build.gradle.
I'm not sure this is worth it however as you will then likely still get hit by the runtime classpath issue (since these folders will still be added to your runtime classpath, your runtime classpath will end-up with two appication.properties resources, one which will 'shadow' the other. See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=482315)
I would say, the right thing to do is add a comment to the issue I linked, and hope they fix it soon as there is only so much you can do yourself by hacking the build.gradle file to modify the .classpath (this can not solve the runtime classpath issue, but in order to solve the runtime classpath issue, they would have to configure source folders to target individual output folder similar to what m2e does).
I would add this as a comment to #Kris's answer but it's too long.
I have solved the runtime classpath issue by adding the code below to my build.gradle file. The code generates an Eclipse launch configuration for the Spring Boot application class and includes only the runtime classpath (i.e. no test JARs).
My project uses the Gradle 'eclipse' plugin to generate the Eclipse project files (which I then import into Eclipse). Running the eclipseClasspath Gradle target will generate the launch file in the project's root directory.
def mainClassName = "com.example.MyApplication"
task eclipseApplicationLaunch {
group "IDE"
description "Generate an Eclipse launch configuration file for the Spring Boot application class"
}
eclipseApplicationLaunch << {
def writer = new FileWriter("${mainClassName.substring(mainClassName.lastIndexOf(".")+1)}.launch")
def xml = new groovy.xml.MarkupBuilder(writer)
xml.doubleQuotes = true
xml.launchConfiguration(type: "org.eclipse.jdt.launching.localJavaApplication") {
listAttribute(key:"org.eclipse.debug.core.MAPPED_RESOURCE_PATHS") {
listEntry(value:"/${project.name}/src/main/java/${mainClassName.replace(".","/")}.java")
}
listAttribute(key:"org.eclipse.debug.core.MAPPED_RESOURCE_TYPES") {
listEntry(value:"1")
}
listAttribute(key:"org.eclipse.jdt.launching.CLASSPATH") {
listEntry(value:"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<runtimeClasspathEntry containerPath=\"org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/\" javaProject=\"${project.name}\" path=\"1\" type=\"4\"/>\r\n")
listEntry(value:"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<runtimeClasspathEntry path=\"3\" projectName=\"${project.name}\" type=\"1\"/>\r\n")
configurations.runtime.resolvedConfiguration.resolvedArtifacts.each { artifact ->
def filePath = artifact.file.canonicalPath.replace("\\","/")
listEntry(value:"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<runtimeClasspathEntry externalArchive=\"${filePath}\" path=\"3\" type=\"2\"/>\r\n")
}
}
booleanAttribute(key:"org.eclipse.jdt.launching.DEFAULT_CLASSPATH", value:"false")
stringAttribute(key:"org.eclipse.jdt.launching.MAIN_TYPE", value:"${mainClassName}")
stringAttribute(key:"org.eclipse.jdt.launching.PROGRAM_ARGUMENTS", value:"--spring.profiles.active=local --spring.config.location=conf/")
stringAttribute(key:"org.eclipse.jdt.launching.PROJECT_ATTR", value:"${project.name}")
stringAttribute(key:"org.eclipse.jdt.launching.VM_ARGUMENTS", value:"-Djava.net.preferIPv4Stack=true")
}
writer.close()
}
eclipseClasspath.dependsOn eclipseApplicationLaunch
I haven't modified the Eclipse .classpath file as per Kris' suggestion. Instead, I have added #Profile("test") to my test application class and #ActiveProfiles("test") to my test classes.

In bndtools, what causes a Require-Capability header for execution environment to be generated?

I have the following bnd file:
Bundle-Version: 1.0.12
Bundle-Activator: a.b.Activator
Private-Package: a.b
-buildpath: osgi.core;version=4.3.0,\
org.apache.felix.bundlerepository;version=1.6.6,\
osgi.cmpn;version=4.3.0.201111022214
-sources: false
In the generated MANIFEST.MF:
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.6))"
I don't want this there... there's no reason I can see that it should be. So how do I avoid it?
bnd 2.3 automatically adds this. You can disable with -noee=true in your bnd file.
Generally this is a good requirement to have since it expresses the base JRE requirement of your bundle. bnd determines the version based upon the class file versions in the bundle.

jar bundle and its classpath in ServiceMix-karaf

I am developing 2 jar files (jar1 and jar2 - the packaging type in pom.xml of 2 jars is jar) and installed them into serviceMix. Jar1 will use some packakes from jar2.
In the manifest.mf files, i used import and export for jar1 and jar2. After installing into serviceMix 4.3.0. Everything going almost fine. From jar 1, i can use packages in jar2 (i know that by debugging the code). But the problem is here:
The structure of Jar2:
jar2:/
.
com
abc
.......(classes)
META-INF
MANIFEST.MF
FactoryContext.xml
The short version of jar2's MANIFEST.MF is
Bundle-ClassPath: .
Bundle-Name: jar2
Bundle-SymbolicName: jar2
Bundle-Version: 1.0.0
Export-Package: com.abc
Import-Package: xyz
Tool: Bnd-1.50.0
Jar1 call a method of Jar2, that method is using bellow statement
context = new ClassPathXmlApplicationContext("FactoryContext.xml");
whenever it goes to this statement, it always throws exception say that FactoryContext.xml doesn not exist. (i guest this file is not in classpath)
Do you know how to make it work?
i also posted my question on ServiceMix forum and i have got the answer from Freeman-2.
Here is the answer
You can try to put FactoryContext.xml in a unique folder like META-
INF/MyFactoryContext/FactoryContext.xml, then jar2 also export package
META-INF.MyFactoryContext, and jar1 import package META-
INF.MyFactoryContext, and then should be able to use code like
context = new ClassPathXmlApplicationContext("META-INF/
MyFactoryContext/FactoryContext.xml");
in jar1.
Here is the link
http://servicemix.396122.n5.nabble.com/question-about-jar-bundle-and-classpath-td5602052.html

Resources