Intellij MANIFEST.MF Not able to resolve Main-Class attribute - maven

I am creating an executable jar file for my project and created the MANIFEST.mf file.
I have changed the location of manifest file to src/main/resources
Although the manifest.mf file is auto generated by intellij, it is still showing me error with Main-Class attribute as 'cannot resolve class'.
My main class look like this:
package runner;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(
strict=true,
monochrome=false,
features = {"src/test/java/features/ALogin.feature",},
glue = {"steps"},
plugin= {
"html:target/site/cucumber-html",
"json:target/cucumber1.json"}
)
public class TestRunner {
public static void main(String[] args){
String[] arguments={"--glue", "steps"};
cucumber.api.cli.Main.main(arguments);
SecurityManager manager = new IgnoreExitCall();
System.setSecurityManager(manager);
try {
cucumber.api.cli.Main.main(arguments);
} catch (SecurityException s) {
System.out.println("Ignore exit");
}
}
}
My MANIFEST.mf like look like this:
Manifest-Version: 1.0
Main-Class: runner.TestRunner
on hovering over Main-Class, it says cannot resolve class 'runner.TestRunner'.
My pom.xml looks like this:
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>
runner.TestRunner
</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>

Related

How to create executable jar in Kotlin using maven-assembly-plugin without a main class?

I want to create an executable jar of my Kotlin codebase using the maven-assembly-plugin. In Kotlin, the main class does not have to be part of a class necessarily but the plugin wants to hear a class.
If I do create a main class, then there is no problem. Let's say I have a main class:
MyApplication.kt
package com.my.application
class MyApplication {
companion object {
#JvmStatic
fun main(args: Array<String>) {
.. do stuff here ..
}
}
}
I also configured the plugin:
pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>
com.my.application.MyApplication
</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
The above works. I can execute the jar successfully. However, there is no need in Kotlin to necessarily have the class with the companion object and then the annotation.
I could just type:
MyApplication.kt
import com.my.application
fun main(args: Array<String>) {
.. do stuff here ..
}
But if I then execute the jar I get an exception:
Error: Could not find or load main class com.my.application.MyApplication
Caused by: java.lang.ClassNotFoundException: com.my.application.MyApplication
How can I make this work?
Kotlin will implicitly compile to a class which is derived from the filename suffixed with Kt. In your case it results to com.my.application.MyApplicationKt
https://kotlinlang.org/docs/java-to-kotlin-interop.html#package-level-functions

Spring Boot Maven Project Obfuscation with Proguard

I am using Java 11, Spring Boot 2.2.4 and Proguard 6.2.2.
My pom.xml for proguard as follows
<build>
<finalName>${artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<proguardVersion>6.2.2</proguardVersion>
<injar>${project.build.finalName}.jar</injar>
<outjar>${project.build.finalName}.jar</outjar>
<includeDependency>true</includeDependency>
<obfuscate>true</obfuscate>
<proguardInclude>${basedir}/proguard.conf</proguardInclude>
<injarNotExistsSkip>true</injarNotExistsSkip>
<libs>
<lib>${java.home}/jmods</lib>
<lib>${java.home}/lib</lib>
</libs>
<archive>
<manifest>
<mainClass>Application</mainClass>
<packageName>com.abc</packageName>
</manifest>
</archive>
</configuration>
<dependencies>
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard-base</artifactId>
<version>6.2.2</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<mainClass>com.abc.Application</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
My Proguard configuration (proguard.conf) as follows
-ignorewarnings
-dontshrink
-dontoptimize
-keepdirectories
-adaptclassstrings
-useuniqueclassmembernames
-dontusemixedcaseclassnames
-flattenpackagehierarchy 'com.abc'
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod
-keep class com.abc.Application
-keep class * extends org.springframework.boot.ApplicationRunner
-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclasseswithmembers,includedescriptorclasses,allowshrinking class * {
native <methods>;
}
When I run the obfucated jar, I am getting below error
Exception in thread "main" java.lang.IllegalStateException: Failed to get nested archive for entry BOOT-INF/lib/spring-boot-starter-data-jpa-2.2.4.RELEASE.jar
Caused by: java.lang.IllegalStateException: Unable to open nested entry 'BOOT-INF/lib/spring-boot-starter-data-jpa-2.2.4.RELEASE.jar'. It has been compressed and nested jar files must be stored without compression. Please check the mechanism used to create your executable jar file

AspectJ binary weaving with Jcabi Maven plugin not working for Kotlin code

I'm trying to run a little annotation over function that will log before and after the method execution.
What I've done: (all classes are under src/main/kotlin)
Annotation class
#Target(AnnotationTarget.FUNCTION)
#Retention(AnnotationRetention.RUNTIME)
annotation class LogMe
Aspect class
import org.aspectj.lang.JoinPoint
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
#Aspect
abstract class Aspect {
#Around("#annotation(LogMe) && execution(* *(..))")
fun logMe(joinPoint: ProceedingJoinPoint): Any {
beforeExecution(joinPoint)
afterExecution(joinPoint)
return joinPoint.proceed()
}
private fun beforeExecution(joinPoint: JoinPoint) {
println("[${joinPoint.signature.name} has started its execution]")
}
private fun afterExecution(joinPoint: JoinPoint) {
println("[${joinPoint.signature.name} has ended its execution]")
}
}
Foo class with annotated method
class Foo {
#LogMe
fun yourMethodAround() {
println("Executing foo.yourMethodAround()")
}
}
main file
fun main(args: Array<String>) {
val foo = Foo()
foo.yourMethodAround()
}
my POM.xml (cut version)
...
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>1.3.40</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>1.3.40</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.4</version>
</dependency>
<!-- TEST -->
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<version>1.3.40</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>
<version>1.3.40</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<jvmTarget>1.8</jvmTarget>
</configuration>
<groupId>org.jetbrains.kotlin</groupId>
<version>1.3.40</version>
<executions>
<execution>
<id>kapt</id>
<goals>
<goal>kapt</goal>
</goals>
</execution>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals> <goal>test-compile</goal> </goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-maven-plugin</artifactId>
<version>0.14.1</version>
<executions>
<execution>
<goals>
<goal>ajc</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>MainKt</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
When I basically run this main, what I'm obtaining is the println that it's into my Foo class method:
Executing foo.yourMethodAround()
But I'm not getting the before and after execution prinln that I was expecting from the Aspect class.
Does any of you ever faced this issue before? This is struggling me, because I can't understand what's going on here.
Disclaimer:
I have never used the Jcabi plugin before, normally I always use AspectJ Maven plugin, also for binary weaving.
I have never used the Kotlin language before, normally I use Java or Groovy.
Now some things are not okay in your aspect:
It must not be abstract, otherwise no instance can be created.
For void methods it must be able to return null, so the Kotlin return type should be Any?
You should proceed() in between the before and after log messages, otherwise the log output will be wrong.
Assuming that your classes, especially the annotation class, do not reside in the default package but have an actual package name, you need to use the fully qualified class name in your pointcut, e.g. #annotation(de.scrum_master.app.LogMe)
Using an aspect class name Aspect, i.e. the same name as the #Aspect annotation, just in another package, is kind of ugly. You should rename it.
For me this works nicely:
package de.scrum_master.aspect
import org.aspectj.lang.JoinPoint
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
#Aspect
class LogAspect {
#Around("#annotation(de.scrum_master.app.LogMe) && execution(* *(..))")
fun logMe(joinPoint: ProceedingJoinPoint): Any? {
beforeExecution(joinPoint)
val result = joinPoint.proceed()
afterExecution(joinPoint)
return result
}
private fun beforeExecution(joinPoint: JoinPoint) {
println("[${joinPoint.signature.name} has started its execution]")
}
private fun afterExecution(joinPoint: JoinPoint) {
println("[${joinPoint.signature.name} has ended its execution]")
}
}
Besides, maybe you also should configure the Jcabi plugin to language level Java 8. It works without it here, but maybe it is better depending on which language features you use:
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
My console after mvn clean verify looks like this:
$ java -jar target/so-aj-kotlin-56890630-1.0-SNAPSHOT.jar
[yourMethodAround has started its execution]
Executing foo.yourMethodAround()
[yourMethodAround has ended its execution]
My IDE IntelliJ IDEA does not quite pick up the binary weaving stuff because it does not know Jcabi, only AspectJ Maven. So I just configured the project to delegate compilation to Maven:
Then the log output is the same when running the application from IDEA directly.

How to define #Parameter annotation in Maven POM

I wrote a Mojo Plugin and set two #Parameter (import org.apache.maven.plugins.annotations.Parameter;)
I want to configure the Parameters in the POM of the project where I want to use this plugin.
No matter where everytime I get an error message.
The part of the POM:
<plugin>
<groupId>com.tup.test</groupId>
<artifactId>versionsextra</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<id>path</id>
<phase>test</phase>
<configuration>
<path>${basedir}/src/main/resources/configsys/dev/etc/deploy_env</path>
</configuration>
</execution>
</executions>
So one of the Parameter is called path:
#Parameter()
private String path;
ok, I got it.
I have to declare it like this:
#Mojo(name="devversion")
public class ParameterMojo extends AbstractMojo {
#Parameter()
private String path;
#Parameter()
private String pathsave;
...
And in POM:
<plugin>
<groupId>com.tup.test</groupId>
<artifactId>versionsextra</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<id>testen</id>
<phase>initialize</phase>
<goals>
<goal>devversion</goal>
</goals>
<configuration>
<path>${basedir}/src/main/resources/configsys/dev/etc/deploy_env</path>
<pathsave>${basedir}/src/main/resources/configsys/dev/etc/test.txt</pathsave>
</configuration>
</execution>
</executions>
</plugin>

calling celery.send_task() from jython fails when using maven

I have the following Java code that uses Jython to call the celery.send_task() method:
import org.python.util.PythonInterpreter;
public class SendTask {
static final String SEND_TASK_PY =
"from celery import Celery\n"+
"c = Celery('tasks', broker='amqp://', backend='amqp://')\n"+
"c.send_task('tasks.add', args=[2, 2], kwargs={})";
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec(SEND_TASK_PY);
}
}
Which results with the following error:
mvn clean package
java -cp target/jython-celery-0.1-SNAPSHOT-jar-with-dependencies.jar SendTask
Exception in thread "MainThread" Traceback (most recent call last):
File "<string>", line 3, in <module>
File "/home/itaif/dev/jython-celery/target/jython-celery-0.1-SNAPSHOT-jar-with-dependencies.jar/Lib/celery/app/base.py", line 245, in send_task
File "/home/itaif/dev/jython-celery/target/jython-celery-0.1-SNAPSHOT-jar-with-dependencies.jar/Lib/celery/app/amqp.py", line 242, in publish_task
File "/home/itaif/dev/jython-celery/target/jython-celery-0.1-SNAPSHOT-jar-with-dependencies.jar/Lib/kombu/messaging.py", line 155, in publish
File "/home/itaif/dev/jython-celery/target/jython-celery-0.1-SNAPSHOT-jar-with-dependencies.jar/Lib/kombu/messaging.py", line 232, in _prepare
File "/home/itaif/dev/jython-celery/target/jython-celery-0.1-SNAPSHOT-jar-with-dependencies.jar/Lib/kombu/serialization.py", line 170, in encode
File "/home/itaif/dev/jython-celery/target/jython-celery-0.1-SNAPSHOT-jar-with-dependencies.jar/Lib/kombu/serialization.py", line 356, in dumps
TypeError: dumps(): takes no keyword arguments
For reference, here is the maven pom.xml that created the jar file:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>jython-celery</groupId>
<artifactId>jython-celery</artifactId>
<packaging>jar</packaging>
<version>0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7-b1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>net.sf.mavenjython</groupId>
<artifactId>jython-compile-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jython</goal>
</goals>
</execution>
</executions>
<configuration>
<libraries>
<param>Celery</param>
</libraries>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>package-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>SendTask</mainClass>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The problem indicated by the error is in the msgpack serializer. By changing the serializer to JSON, the problem disappears.
import org.python.util.PythonInterpreter;
public class SendTask {
static final String SEND_TASK_PY =
"from celery import Celery\n"+
"c = Celery('tasks', broker='amqp://', backend='amqp://')\n"+
"c.conf.CELERY_TASK_SERIALIZER='json'\n"+
"result = c.send_task('tasks.add', args=[2, 2], kwargs={}).get()";
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec(SEND_TASK_PY);
System.out.println(interpreter.get("result"));
} }

Resources