Quarkus native build class in both build and run time initialization - java

I have a 3rd party class which is added to build time initialization by Quarkus, but it requires run time initialization due to static thread usage. When adding it to run time initialization native build then complains about it being in both.
Example project which re-produces this: https://github.com/hshorter/quarkus-avro-decode-example
With "--initialize-at-run-time=org.apache.avro.specific.SpecificDatumReader":
Error: Classes that should be initialized at run time got initialized
during image building: org.apache.avro.specific.SpecificDatumReader
the class was requested to be initialized at build time (from the
command line). To see why
org.apache.avro.specific.SpecificDatumReader got initialized use
-H:+TraceClassInitialization
Without "--initialize-at-run-time=org.apache.avro.specific.SpecificDatumReader":
Error: Detected a started Thread in the image heap. Threads running in
the image generator are no longer running at image run time. To see
how this object got instantiated use -H:+TraceClassInitialization. The
object was probably created by a class initializer and is reachable
from a static field. You can request class initialization at image run
time by using the option --initialize-at-build-time=. Or
you can write your own initialization methods and call them explicitly
from your main entry point. Detailed message: Trace: object
org.apache.avro.specific.SpecificDatumReader
Any help much appreciated.

We just fought through this, in the generated code there's a static initializer like this:
private static BinaryMessageEncoder ENCODER = new BinaryMessageEncoder(MODEL$, SCHEMA$);
private static BinaryMessageDecoder DECODER = new BinaryMessageDecoder(MODEL$, SCHEMA$);
We modified the Velocity templates in the Avro code generation to:
Add the #io.quarkus.runtime.annotations.RegisterForReflection annotation
initialize the statics in the constructor using lazy initialization.
Remove those classes from the runtime class init.
The downside is that you have to maintain your custom codegen templates. It's relatively easy though, here's the maven config to automate your codegen:
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>${avro.version}</version>
<executions>
<execution>
<id>schemas</id>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
<configuration>
<templateDirectory>${project.basedir}/src/main/resources/avro/templates/</templateDirectory>
</configuration>
</execution>
</executions>
</plugin>
you can find the base templates at https://github.com/apache/avro/tree/master/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic

Sorry, I'm late to the party but the issue you have here is that while you asked SpecificDatumReader to be initialized at runtime, another class initialized at build time requires SpecificDatumReader to be initialized.
So basically, you have some detective work to do to determine why this class was initialized and probably mark the class initializing that one as runtime initialized too.
Note that sometimes it can be a bit hairy.

Related

TestNG parallel classesAndMethods without XML

I'm trying to have both classes and methods running in parallel.
For example:
Method Tests
public class MethodTests(){
#Test(groups = "testMe")
public void methodTestOne(){
...
}
#Test(groups = "testMe")
public void methodTestTwo(){
...
}
}
Class Tests
-> Hoping the Test annotation on the class level would do it
#Test
public class ClassTests(){
#Test(groups = "testMe")
public void classTestOne(){
...
}
#Test(groups = "testMe")
public void classTestTwo(){
...
}
}
I've included the surefire-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<parallel>all</parallel>
<threadCount>${threads}</threadCount>
...
</plugin>
Note: I've also tried classesAndMethods
I'm running from the command line like this:
mvn clean verify -Dgroups=testMe -Dthreads=3
I'm trying to accomplish the classTests run on one thread, and the method tests use a different thread after being complete.
Purpose:
In the beforeClass, I'm setting up the test, and then quickly asserting multiple things on a page, If one fails, I want it to still test the other things on the page.
Where as, if the method tests fail, I need it to completely stop.
I need both scenarios, and I do not want to use any XML.
I am not sure I quite understand the use case. But the only combinations of parallelism supported by TestNG are as below
tests - causes #Test methods inside tags to run in parallel.
instances - Causes #Test methods inside test class instances to run in parallel.
classes - causes test classes to run in parallel
methods - causes multiple #Test methods to run in parallel
I dont remember seeing something called all. I think that's applicable only to the JUnit provider for Maven surefire plugin. Please see here.
For your scenario as long as you have the #BeforeClass(alwaysRun=true) it would be executed for all groups and it would prevent the test methods that are dependent on the before class to be skipped.
The value that you should be using is classes, like this : <parallel>classes</parallel>

Why is a directory referenced as a classpath resource null if the directory is empty?

I've got the following unit test class, which referenced some test data files as classpath resources:
package com.altanqa.project.parser;
public class ParserTest {
private static final URL VALID_DIR = ParserTest.class.getResource("testData-VALID");
private static final URL INVALID_DIR = ParserTest.class.getResource("testData-INVALID");
private static final URL MISSING_DIR = ParserTest.class.getResource("testData-MISSING");
// ...
}
The directory structure referenced here looks like this:
src/test/java/com/altanqa/project/parser
ParserTest.java
src/test/resources/com/altanqa/project/parser
testData-VALID
data
test-data.txt
testData-INVALID
data
test-data.txt
testData-MISSING
data
The Parser under test takes a directory, and knows to look in it for data/testData.txt. The test class here runs the parser, giving it valid data, invalid data, and missing data, to check that the parser deals with each situation correctly. Valid and invalid data works fine, but the MISSING URL is null. If I put a different file (say, a.txt) in test-data-MISSING, the URL is properly initialised, but without any files in the directory, it is null. Is this a peculiarity of the class loader? Is there a way around it, i.e. to have the MISSING_DIR URL initialise correctly, even with nothing in its subdirectory?
Thank you!
Credit goes to Boris for highlighting that this is a Maven issue, rather than anything with the Java. The maven-resources-plugin needs to be configured to include empty directories when copying resources. In the pom:
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
...
<configuration>
<includeEmptyDirs>true</includeEmptyDirs>
</configuration>
...
</plugin>
</plugins>
</build>

Maven 2 reports 'java.util.List' cannot be instantiated error

A user has reported that a maven plugin I maintain no longer works with maven 2 (it runs just fine under maven 3). It fails to parse the pom with the error
Cause: Class 'java.util.List' cannot be instantiated
A quick Google suggests that this is a bug in the maven model prior to 3.0 that has affected other plugins.
http://code.google.com/p/maven-samaxes-plugin/issues/detail?id=18
I recently added support for setting values via the command line by specifying expressions for List parameters, and it appears that this has triggered the bug.
/**
* #parameter expression="${targetClasses}"
*/
protected List<String> targetClasses;
I can work around the problem by declaring the field as a concrete list type, but everyone knows that a fairy dies each time you do this.
Are there any nicer soloutions to this problem apart from withdrawing support for maven 2 or using concrete types?
This is quite old now and you've answered your own question, I guess... Still, for completeness, here goes:
I'm using mvn 2.0.9 and had to migrate from List<String>:
/**
* #parameter expression="${arguments}"
*/
protected List<String> arguments; //with or without generics, still complained!
to String[]:
/**
* #parameter expression="${arguments}"
*/
protected String[] arguments;
The pom configuration is then as follows:
<configuration>
...
<arguments>
<argument>arg1</argument>
<argument>arg2</argument>
</arguments>
</configuration>

Maven Codehaus findbugs plugin "onlyAnalyze" option not working as expected

Update for the impatient: it's simple, use package.- for sub-package scanning instead of package.*, as-per martoe's answer below!
I cannot seem to get onlyAnalyze working for my multi-module project: regardless of what package (or pattern) I set, maven-findbugs-plugin doesn't evaluate sub-packages as I'd expect from passing it packagename.*.
To prove either myself or the plugin at fault (though I always assume it's the former!), I setup a small Maven project with the following structure:
pom.xml
src/
main/java/acme/App.java
main/java/acme/moo/App.java
main/java/no_detect/App.java
which is very simple!
The POM has the following findbugs configuration:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.4.0</version>
<executions>
<execution>
<phase>verify</phase>
<goals><goal>findbugs</goal><goal>check</goal></goals>
</execution>
</executions>
<configuration>
<debug>true</debug>
<effort>Max</effort>
<threshold>Low</threshold>
<onlyAnalyze>acme.*</onlyAnalyze>
</configuration>
</plugin>
</plugins>
</build>
and every App.java has the following code with two obvious violations:
package acme;
import java.io.Serializable;
public class App implements Serializable
{
private static final class NotSer {
private String meh = "meh";
}
private static final NotSer ns = new NotSer();// Violation: not serializable field
public static void main( String[] args )
{
ns.meh = "hehehe";// Vilation: unused
System.out.println( "Hello World!" );
}
}
Note that no_detect.App has the same content as above, but my expectation is that it wouldn't be evaluated by findbugs because I have the "onlyAnalyze" option set to acme.* which I assume would evaluate acme.App and acme.moo.App and nothing else.
I now execute a mvn clean install to clean, build, test, run findbugs, package, install, which produces the following findbugs report (snipped for brevity) and results in a build failure which is expected because acme.App and acme.moo.App:
<BugInstance category='BAD_PRACTICE' type='SE_NO_SERIALVERSIONID' instanceOccurrenceMax='0'>
<ShortMessage>Class is Serializable, but doesn't define serialVersionUID</ShortMessage>
<LongMessage>acme.App is Serializable; consider declaring a serialVersionUID</LongMessage>
<Details>
<p> This field is never read.&nbsp; Consider removing it from the class.</p>
</Details>
<BugPattern category='BAD_PRACTICE' abbrev='SnVI' type='SE_NO_SERIALVERSIONID'><ShortDescription>Class is Serializable, but doesn't define serialVersionUID</ShortDescription><Details>
<BugCode abbrev='UrF'><Description>Unread field</Description></BugCode><BugCode abbrev='SnVI'><Description>Serializable class with no Version ID</Description></BugCode>
To summarise: only acme.App is analysed, acme.moo.App isn't (bad) and neither is no_detect.App (good).
I tried with two wildcards in the onlyAnalyze option but that produces a successful build but with a findbugs error (Dangling meta character '*' etc).
I tried with onlyAnalyze set to acme.*,acme.moo.* which analyzes all the expected classes (acme.App and acme.moo.App) which means it "works" but not as I expect; i.e. I have to explicitly declare all parent-packages for the classes I want to analyze: that could get large and difficult to maintain on a multi-module project!
Do I have to define every package I want analyzed, or can I declare a wildcard/regex pattern that will do what I want?
I'd rather not use the inclusion/exclusion XML because that requires far more setup and reasoning that I don't currently have time for...
To cite the Findbugs manual: "Replace .* with .- to also analyze all subpackages"

NoAspectBoundException with aspectj and tapestry 5

I have a web project built with Tapestry 5.2.1. I have a simple logging aspect that I was using for tracing on this application. Everything was working fine until I started refactoring parts of the application and attempted to deploy it.
When I deploy the application, no matter what page I attempt to go to I get the following exception:
Caused by: java.lang.RuntimeException: Exception assembling root component of page Index: Exception while initializing TraceAspect: org.aspectj.lang.NoAspectBoundException: TraceAspect
at org.apache.tapestry5.internal.pageload.ComponentAssemblerImpl.performAssembleRootComponent(ComponentAssemblerImpl.java:124)
at org.apache.tapestry5.internal.pageload.ComponentAssemblerImpl.access$000(ComponentAssemblerImpl.java:38)
at org.apache.tapestry5.internal.pageload.ComponentAssemblerImpl$1.invoke(ComponentAssemblerImpl.java:82)
at org.apache.tapestry5.internal.pageload.ComponentAssemblerImpl$1.invoke(ComponentAssemblerImpl.java:79)
at org.apache.tapestry5.ioc.internal.OperationTrackerImpl.invoke(OperationTrackerImpl.java:65)
... 73 more
Caused by: org.aspectj.lang.NoAspectBoundException: Exception while initializing TraceAspect: org.aspectj.lang.NoAspectBoundException: TraceAspect
at TraceAspect.aspectOf(TraceAspect.aj:1)
at com.wex.rrt.wrightweb.reportrequest.webapp.pages.Index.initializer(Index.java:3)
at com.wex.rrt.wrightweb.reportrequest.webapp.pages.Index.<init>(Index.java)
at $Instantiator_12d4da06f67.newInstance($Instantiator_12d4da06f67.java)
at org.apache.tapestry5.internal.structure.InternalComponentResourcesImpl.<init>(InternalComponentResourcesImpl.java:146)
at org.apache.tapestry5.internal.structure.ComponentPageElementImpl.<init>(ComponentPageElementImpl.java:593)
at org.apache.tapestry5.internal.structure.ComponentPageElementImpl.<init>(ComponentPageElementImpl.java:609)
at org.apache.tapestry5.internal.pageload.ComponentAssemblerImpl.performAssembleRootComponent(ComponentAssemblerImpl.java:93)
... 77 more
Caused by: org.aspectj.lang.NoAspectBoundException: TraceAspect
at TraceAspect.aspectOf(TraceAspect.aj:1)
at AbstractLoggingAspect.<init>(AbstractLoggingAspect.aj:7)
at TraceAspect.<init>(TraceAspect.aj:12)
at TraceAspect.ajc$postClinit(TraceAspect.aj:1)
at TraceAspect.<clinit>(TraceAspect.aj:1)
... 84 more
My aspect has remained unchanged and is this:
#Aspect
public class TraceAspect {
Logger logger = Logger.getLogger("trace");
public TraceAspect() {
logger.setLevel(Level.ALL);
}
/**
* Will log every execution of
* <ul>
* <li>doEverything</li>
* <li>doSomething</li>
* </ul>
* excluding any test classes.
*/
#Pointcut("(execution(public void *(..)) || execution(*.new(..))) && !within(*Test) !within(com.aspects.*)")
protected void logging() {
}
#Around("logging()")
public void doThing(final ProceedingJoinPoint thisJoinPoint) throws Throwable {
final String joinPointName = thisJoinPoint.getThis().getClass().getSimpleName() + "." + thisJoinPoint.getSignature().getName() + "()";
logger.info("Entering [" + joinPointName + "]");
thisJoinPoint.proceed();
logger.info("Leaving [" + joinPointName + "]");
}
}
During compilation everything works fine. I'm using the maven plugin to compile the aspects:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.3</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<complianceLevel>1.6</complianceLevel>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
I've been working at this off and on for most of the day and haven't gotten anywhere. I'm not exactly understanding the NoAspectBoundException. It would seem that the compiler is not weaving the aspect completely? I'm new to AspectJ but I'm wondering if this is something to do with Tapestry5. Although I know that Tap5 uses AOP though.
As I said, this was all working as is just fine until I moved some things into a separate tapestry custom library that is now a dependency for my web app.
You are advising the aspect's constructor due to the unrestricted execution(*.new(..)) part of the pointcut. When the aspect is being instantiated, the advice doesn't have an instance of the aspect, hence the error. You should be able to fix this by adding !within([package of].TraceAspect).
I think we are having a conflict of AOP. AspectJ has done something to the code, and then Tapestry comes along and does something else ... including ignoring existing Class constructors on the component class and adding its own. I'm not sure how to get the two working together.
I know it is too late to answer this question. But as I understand it's better to don't use aspectj with the tapestry. If you want to use it you must not define the #Aspect class as a tapestry component. Just move the class to another path (anywhere except the pages package).

Categories