How to annotate java package and reflect metadata - java

I would like to annotite java package using simple annotation:
#Target(ElementType.PACKAGE)
public #interface Related {
int apiVersion() default 0;
}
However when I try to add it to any package I've got compilation error
Error:(1, 14) java: cannot find symbol
symbol: class Related
location: package com.test.xxx
Any help appreciated!
EDIT
After searching a bit I found also this kind of error
Error:(1, 1) java: package annotations should be in file package-info.java

To be able to place annotation on package you should create package-info.java file which should contain package definition like this:
#Related
package tld.some.name;
To be able to reflect reflect package you also need to set up RetentionPolicy.RUNTIME
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PACKAGE)
public #interface Related {
// stuff...
}
And then you can finally reflect package:
SomeClassInPackage.class.getPackage().getAnnotation(Related.class)
You can also reflect package by name using java.lang.Package
Package.getPackage("tld.some.name").getAnnotation(Related.class)

Related

mapstruct v1.3.1FINAL: imports from static methods aren't generated

We are using mapstruct 1.3.1FINAL (in combination with lombok v1.18.4 if that matters) and the generated classes aren't compiling because the imports of the static methods used in expression mappings aren't generated. Any clues?
#Mapping(target = "value", expression = "java(ValueUtil.getValue(sourceValue))")
The generated code has compilation errors because the import of ValueUtil is missing :
request.setValue( ValueUtil.getValue(sourceValue) );
Finally i got it, tried out what Sjaak wrote.
#Mapper(imports = { ValueUtil.class })
The import made it. Will try out if Deepaks answer works as well.
Please try with fully qualified class name for ValueUtil I.e. packagename.ValueUtil. This will provide the context to mapstruct to locate the class.
you can add an import statement to the #Mapper annotation, precisely for such cases. Checkout the documentation.

Converting package level Java annotation to Kotlin

Is it possible to convert a package level Java annotation to Kotlin?
Java annotation (MyAnnotation.java):
package com.myexample.annotation;
#Retention(RUNTIME) #Target(PACKAGE)
public #interface MyAnnotation {
}
Application of annotation (package-info.java)
#MyAnnotation
package com.myexample
The following does not seem to work (although it does compile) - my annotation processor does not detected any of the classes in the package com.myexample:
MyAnnotation.kt
package com.myexample.annotation
#Target(allowedTargets = [AnnotationTarget.CLASS, AnnotationTarget.FILE])
#Retention(AnnotationRetention.SOURCE)
annotation class MyAnnotation
package-info.kt
#file:MyAnnotation
package com.myexample
import com.myexample.annotation.MyAnnotation
No, it's not currently possible. You can simply leave package-info.java as a Java file.

Using LocalDateTime with JAXB

I am trying to use JAXB with fields of the LocalDateTime type. I wrote an adapter to handle conversion:
public class LocalDateTimeXmlAdapter extends XmlAdapter<String, LocalDateTime> {
#Override
public String marshal(LocalDateTime arg0) throws Exception {
return arg0.toString();
}
#Override
public LocalDateTime unmarshal(String arg) throws Exception {
return LocalDateTime.parse(arg);
}
}
I registered the adapter in package-info.java like so:
#XmlJavaTypeAdapters({
#XmlJavaTypeAdapter(type=LocalDateTime.class, value=LocalDateTimeXmlAdapter.class)
})
package xml;
import java.time.LocalDateTime;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
This seems to be sufficient according to this page.
However, I keep getting the following error:
com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.time.LocalDateTime does not have a no-arg default constructor.
I understand the reason for the exception being thrown, but I can hardly add a default constructor to java.time.LocalDateTime. This seems to be a shortcoming of the class / a strange design decision. Are there any workarounds?
What you have should work. One of the following may be wrong:
Since you have specified the #XmlJavaTypeAdapter at the package level it will only apply to properties on classes in your package called xml. Is there a class in your model from a different package that has a mapped property of type LocalDateTime?
It is also possible that your package-info.java file is not being compiled.
Had same behaviour: IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions.
My pbm was: I have several packages (three) where the package-info.java file is needed, like shown in the following picture.
I "solved" this pbm by adding a package-info.java in each of the three directories. Example for package fr.gouv.agriculture.dal.ct.planCharge.metier.dao.charge.xml:
#XmlJavaTypeAdapter(type = LocalDate.class, value = LocalDateXmlAdapter.class)
package fr.gouv.agriculture.dal.ct.planCharge.metier.dao.charge.xml;
If someone has a better idea than copy/paste into several package-info.java files, thanks in advance.

Importing and Packages

I'm not quite sure what I'm doing wrong, here. I have two files in a directory, let's call them FileA.java and FileB.java.
FileA.java has a definition along the lines of:
package com.domain.package;
import stuff;
import package.FileB;
public class FileA extends Blah implements Listener {
/* global vars */
/* methods */
}
FileB.java is my data object class, which I'd like to reference from FileA.java thusly:
Map<Object, FileB> varname;
to be used along the lines of:
varname = new HashMap<Object, FileB>();
FileB.java, on the other hand, is defined as such:
package com.domain.package;
import stuff;
public class FileB {
/* global vars */
public FileB() {
/* stuff */
}
}
Why am I getting:
FileA.java:20: package package does not exist
import package.FileB;
? Rather, how do I make it work?
Because both files are in the same package (com.domain.package), you should not need to import FileB at all. You should be able to reference it directly.
Additionally, please ensure that both FileA and FileB are placed in their package folder: com/domain/package.
The package of FileB is com.domain.package. You are trying to use package.FileB instead.
package is a reserved word, don't use it as part of a package name. If you try to add a package with "package" as part of it in Eclipse, you will get an error message:
Invalid package name. 'package' is not a valid Java identifier
Rename the package, then remove the import statement. You don't need to import a file that's in the same package as the one it's referenced in.
#rgettman has the correct solution. Compiling both files using javac FileA.java FileB.javasolves this issue. You can also use his suggestion: javac *.java

incompatible types found: required: default enums in annotations

[javac] C:\ws\galileo\test\Cacheable.java:13: incompatible types
[javac] found : com.io.CacheType
[javac] required: com.io.CacheType
[javac] public CacheType id() default CacheType.COMMON;
I really don't get this one.
I have a project where I'm custom building a caching interceptor for Spring. It simply is a look by cache name to point to EhCache and uses aop-autoproxy to load the CacheableAspect (which is my caching intercepter). Now when I use the default value in the annotation, ANT gives me the compiler error below. I tried updating to the latest JDK (i'm on 1.6 16 now) and setting source/target levels in the ant script but no success. When I remove the default value and force all areas to specify a value, it compiles in ant fine.
It always worked in Eclipse, I had unit tests that ran perfectly with the previous default value.
What gives? I tried building a project (no spring) that simply echoed the configuration with ant and it compiled in ant fine (and in eclipse).
that tells me MAYBE it might be the spring auto-proxying somehow? but then why would the compiler not give me the generated type name? GRRRR. Any thoughts?
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.io.CacheType;
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD})
public #interface Cacheable {
public CacheType value() default Cachetype.COMMON;
}
public enum CacheType {
COMMON("common"),
PERSISTENT("persistent";
private String cache;
CacheType(String cache) {
this.cache = cache;
}
public String cache() {
return this.cache;
}
}
Still present in JDK 6u25, but adding package to default value does the trick:
CacheType value() default com.io.CacheType.COMMON;
Have a look here:
http://bugs.sun.com/view_bug.do?bug_id=6512707
this might be the cause of your problem.
So just a little update. While the bug tracker shows the bug as closed and seems to want to refute any new openings of the bug. When I encountered this bug in this example revolves around the compile time annotation processor. Since the retention is RUNTIME which means it does not require a compile time annotation processor it appears that the compile time annotation processer is blowing up the compile process. Whenever I am in NetBeans and I have compile time annotations enabled under Build->Compiling in the projects properties I receive a nebulous series of errors.
I am going to attempt opening a new bug ticket for the issue and just thought I would pass on the easy workaround for now.
Still present using javac 1.6.0_26. yurez's workaround of using the fully qualified type name when specifying the default value still works.
Found this bug is solved in 1.6.0_31 and 1.7.0_03 (maybe also in some previous versions), so just upgrade the java compiler.
I wonder if it this is caused by defining Cacheable and CacheType in the same source file, and then importing "com.io.CacheType". That could conceivably make the compiler think that there are two classes called "com.io.CacheType".
Could you post the entire source file or something? The code you posted seems copy/pasted from different source files and is full of typos.
Normally the following should always do the trick when CacheType enum is in a different source file, you had a typo in CacheType.COMMON:
public #interface Cacheable {
public CacheType value() default CacheType.COMMON;
}
Works with a Fully qualified type name.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.io.CacheType;
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD})
public #interface Cacheable {
public CacheType value() default com.io.Cachetype.COMMON;
}

Categories

Resources