Codename One: Annotation Processing - java

I have a Codename One project on Netbeans using their plugin.
Is there a way to make it work? I enabled it in project's settings and still doesn't show in final jar.
The annotations are in the libraries of the project. and I can see it being done in the output:
warning: Supported source version 'RELEASE_6' from annotation processor 'org.netbeans.modules.openide.util.ServiceProviderProcessor' less than -source '1.8'
I used instructions here: https://netbeans.org/kb/docs/java/annotations-lombok.html
Update:
I thought it was clear but seems it's not. All this is using Netbean's Lookup. Let's say I have one jar as project dependency with one interface in it, let's say ITest. Also a class implementing the interface, for example:
#ServiceProvider(service=ITest.class)
public class Test implements ITest{
..
}
So in the Codenamone Project I call it like this:
Lookup.getDefault().lookupAll(ITest.class);
But it come up empty. I know the system works as it does in other projects, just porting it to Codename one. Seems like it is not seeing the annotations in the dependencies.

I don't know if that will work and I'm pretty curious about it myself. Make sure you created a Java 8 version of the project and you are running on top of Java 8 to get started.
In the past things like this were done using bytecode manipulation e.g. see this code from the work done by Steve.

Related

Unable to use AbstractProcessor in IDEs

Motivation:
In our code we have a few places where some methods are run by their name. There are some big if-else-if blocks with each function name and call of the corresponding method (I use the term function to describe just names, for example function X01 might correspond to method SomeClass.functionX01). I've been looking into ways to improve that
Goal:
Write just methods that are annotated with some custom annotation, removing the need to update or even include if-else-if blocks in order to run specific function. Have access to any generated code if any code is generated.
What I did:
I've created first prove of concept using runtime annotations and it proved successful, but slower then if-else-if. Next attempt was with source annotation
I've followed this link for an example, however it did not seam to run in IntelliJ. What I wanted is to have - in this case PersonBuilder class generated, instead there was none. In some cases an error was raised Error:java: Bad service configuration file, or exception thrown while constructing Processor object: javax.annotation.processing.Processor: Provider BuilderProcessor not found
After some Googling and failing to find anything I've turned to book (Core Java, Volume II - Advanced Features - 9th Edition, Polish translation) and there was reccomended to run the following commands:
javac [AbstractProcessor implementation]
javac -processor [Compiled Processor] [other source files to compile]
This worked, however is unsatisfactory as it needs to happen inside IDE (NetBeans and IntelliJ to be specific) automatically during build. Code does not need to be generated on the fly, but programmer must have access to it after build (as in - be able to call methods of generated classes)
Question:
How to have and use generated code used in NetBeans and IntelliJ without the need of using external tools? Is it possible, or using reflection, runtime annotations or external tools is the only way?
Additional info (just in case):
Language level: Java 1.8
JVM versions: 12 and 13
IDEs: NetBeans and IntelliJ

warning: No processor claimed any of these annotations: javax.annotation.Generated

I'm working on a module project in NetBeans 8.2, with a GUI and everything. I'm using lots of the IDE functionality to auto-generate code for the GUI.
Every time I do a clean build of my project, I get a warning from the compiler:
warning: No processor claimed any of these annotations:javax.annotation.Generated
Browsing the build directory, I see that the IDE generates a class for me, Bundle.java, and it slaps the given annotation on top of it:
#javax.annotation.Generated(value="org.netbeans.modules.openide.util.NbBundleProcessor")
I need this warning to go away. I tried searching the web for an annotation processor that processes this specific annotation but I had no luck. Does an annotation processor for this specific annotation exist?
If this is a "harmless warning," I need to understand why it is harmless to justify its existence in my build output.
If needed I can include in this question the argument to the -processorpath option that is passed to javac from the IDE; I didn't include it on purpose because it is very long but I can add it if necessary
EDIT #1:
I did a "hacky" modification to the common.xml file under the NetBeans installation directory to make the invocation to javac not include the -processorpath option, and doing so makes the warning dissapear. I still do not understand why that is the case
A simple fix for this is to remove the #Messages annotation from the TopComponent class that is generated by the NetBeans code generator. It is that annotation that is responsible for generating the Bundle class, as per the NbBundle.Messages API Documentation.
As soon as you remove that annotation, you might get warnings from other annotations that rely on the contents of the #Messages annotation (i.e. TopComponent.OpenActionRegistration), so make sure to modify the contents of those annotation as well until nothing in your code depends on that Bundle anymore.
Hopefully nothing else in your code relies on your Bundle.

Java package versions - getting it right

I would like to get deeper understanding on how Java deals with different versions of Classes/Packages/etc., but couldn't find any resources or at least the best way to google for it. The problem is as follows.
Imagine we have some external package com.external.package that contains a definition of SomeInterface.
Now I write a java class MyClass that implements SomeInterface, and using com.external.package v1.0.0. Next I package a (lean) jar containing MyClass.
Now I plug this jar in another program that is looking for implementations of SomeInterface, but in it's dependencies, it is using com.external.package v2.0.0.
Is the reason I get Failed to find any class that implements SomeInterface that versions of SomeInterface don't match in the program and in the jar that contains a class extending it?
Basically the question I would like to find an answer for is what info do jars store regarding external dependencies? Does it store the exact versions of them and if they don't match at the runtime it complains? But why does it even allow running the program with references to same dependency, but different versions?
Is the reason I get Failed to find any class that implements SomeInterface that versions of SomeInterface don't match in the program and in the jar that contains a class extending it?
There is no "versioning" happening here. Simply, the error states no such class exists on the classpath. For example, you didn't put a -cp in your java command to add that extra JAR/class file.
Other reasons this could happen is that an API marks a class as deprecated in v1, then decides to remove it from v2. In which case, you best try to compile and test your code against the proper library versions before you package your own code. If you made an uber JAR, the classes should get shaded, and you probably wouldn't have missing classes.
Maven projects do have the concept of transitive, versioned dependencies, but you've not said anything about that
Seeing that the original question has found an answer already, it seems somewhat relevant to mention that Java Packages and JARs could be used for specifying package version information as discussed in the following documentation:
https://docs.oracle.com/javase/8/docs/technotes/guides/versioning/spec/versioning2.html#wp89936
Also, the Oracle Java Tutorials discuss them and further concepts around deployment of programs as JAR Files as documented here:
https://docs.oracle.com/javase/tutorial/deployment/jar/index.html

Can Gradle help solve jar hell in any way?

Java 8 here.
Say there is an old version of the widget libray, with Maven coordinates widgetmakers:widget:1.0.4, that has a class defined in it like so:
public class Widget {
private String meow;
// constructor, getters, setters, etc.
}
Years pass. The maintainers of this widget library decide that a Widget should never meow, rather, that it should in fact bark. And so a new release is made, with Maven coordinates widgetmakers:widget:2.0.0 and with Widget looking like:
public class Widget {
private Bark bark;
// constructor, getters, setters, etc.
}
So now I go to build my app, myapp. And, wanting to use the latest stable versions of all my dependencies, I declare my dependencies like so (inside of build.gradle):
dependencies {
compile (
,'org.slf4j:slf4j-api:1.7.20'
,'org.slf4j:slf4j-simple:1.7.20'
,'bupo:fizzbuzz:3.7.14'
,'commons-cli:commons-cli:1.2'
,'widgetmakers:widget:2.0.0'
)
}
Now let's say that this (fictional) fizzbuzz library has always depended on a 1.x version of the widget library, where Widget would meow.
So now, I'm specifying 2 versions of widget on my compile classpath:
widgetmakers:widget:1.0.4 which is pulled in by the fizzbuzz library, as a dependency of it; and
widgetmakers:widget:2.0.0 which I am referencing directly
So obviously, depending on which version of Widget gets classloaded first, we will either have a Widget#meow or a Widget#bark.
Does Gradle provide any facilities for helping me out here? Is there any way to pull in multiple versions of the same class, and configure fizzbuzz classes to use the old version of Widget, and my classes to use the new version? If not, the only solutions I can think of are:
I might be able to accomplish some kind of shading- and/or fatjar-based soltuion, where perhaps I pull in all my dependencies as packages under myapp/bin and then give them different version-prefixes. Admittedly I don't see a clear solution here, but am sure something is feasible (yet totally hacky/nasty). Or...
Carefully inspect my entire dependency graph and just make sure that all of my transitive dependencies don't conflict with each other. In this case for me, this means either submitting a pull-request to the fizzbuzz maintainers to upgrade it to the latest widget version, or, sadly, downgrading myapp to use the older widget version.
But Gradle (so far) has been magic for me. So I ask: is there any Gradle magic that can avail me here?
Don't know the specifics of Gradle, as I'm a Maven person, but this is more generic anyway. You basically have two options (and both are hacky):
ClassLoader magic. Somehow, you need to convince your build system to load two versions of the library (good luck with that), then at runtime, load the classes that use the old version with a ClassLoader that has the old version. I have done this, but it's a pain. (Tools like OSGI may take away some of this pain)
Package shading. Repackage the library A that uses the old version of library B, so that B is actually inside A, but with a B-specific package prefix. This is common practice, e.g. Spring ships its own version of asm. On the Maven side, the maven-shade-plugin does this, there probably is a Gradle equivalent. Or you can use ProGuard, the 800 pound gorilla of Jar manipulation.
Gradle will only set up the classpath with your dependencies, it doesn't provide its own runtime to encapsulate dependencies and its transitive dependencies. The version active at runtime will be the one according to the classloading rules, which I believe is the first jar in the classpath order to contain the class. OSGI provides runtime that can deal with situations like this and so will the upcoming module system.
EDIT: Bjorn is right in that it will try to resolve conflicts in different versions; it'll compile the classpath based on its strategies, so the order you put your dependencies in the file doesn't matter. However you still only get one class per classname, it won't resolve OP's issue
If you have different versions of a library with otherwise equal coordinates, Gradles conflict resolution mechanism comes into play.
The default resolution strategy is to use the newest requested version of the library. You will not get multiple versions of the same library in your dependendcy graph.
If you really need different versions of the same library at runtime you would have to either do some ClassLoader magic which definitely is possible or do some shading for one of the libraries or both.
Regarding conflict resolution, Gradle has built-in the newest strategy that is default and a fail strategy that fails if different versions are in the dependency graph and you have to explicitly resolve version conflicts in your build files.
Worse case is when the same class appears in multiple jars. This is more insidious - look at the metrics jars from Codahale and Dropwizard with incompatible versions of the same class in the two jars.
The gradle classpath-hell plugin can detect this horror.

Annotation for GWT compiler to ignore method

Is it possible to create an annotation (or some other way) to force the GWT compiler to not compile a method? I have a class that I also use on app-engine (in a shared folder) and one method in it requires a server side only function which causes GWT to not compile. I would like GWT to just ignore the method (while appengine does not).
I figured either an annotation, or a pre-compile script that erases the method prior to compilation. Both methods would work for me, it would be best if I could still compile through the eclipse IDE.
Anyone else thought of this or tried it?
Not until now. Very recently such annotation was added #com.google.gwt.core.shared.GwtIncompatible("Description why..."). It is applicable on classes or methods.
But the patched code was not released yet! Official status is FixedNotReleased. And i can personally confirm, it is not in current GWT 2.5.1 version. I am hopeful for upcoming 2.5.2.
See:
http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/core/shared/GwtIncompatible.java?spec=svn11570&r=11570
http://code.google.com/p/google-web-toolkit/issues/detail?id=3769
https://gwt-review.googlesource.com/#/c/2320/
Note, there is already similar annotation com.google.gwt.thirdparty.guava.common.annotations.GwtIncompatible in gwt-dev.jar, however
it does not work, compiler still wants to compile my incompatible method in shared class.
Prior to GWT version 2.6, there is no annotation to make the GWT compiler ignore a method. There is a requests for it in the GWT issue tracker, and apparently it is scheduled for the 2.6 release.
One workaround approach is to have the "offending" method in a class of its own and ignore that class in your .gwt.xml file:
<source path="gwtclient">
<exclude name="AppEngineOnlyClass.java" />
...
</source>
...
Hope that helps a bit.
Cheers,

Categories

Resources