How to build a rule: assignableTo metaannotated? - java

I want to find all classes that are metaAnnotated or are assignableTo metaannotated with any version of Immutable annotation.
That is all classes metaAnnotated as immutable or implementing / extending anything that's metaAnnotated as immutable.
I tried:
DescribedPredicate m = simpleNameEndingWith("Immutable");
DescribedPredicate a = CanBeAnnotated.Predicates.metaAnnotatedWith(m);
System.out.println(productionClasses.that(a));
but it throws runtime exception:
java.lang.ClassCastException: class com.tngtech.archunit.core.domain.JavaAnnotation cannot be cast to class com.tngtech.archunit.core.domain.JavaClass (com.tngtech.archunit.core.domain.JavaAnnotation and com.tngtech.archunit.core.domain.JavaClass are in unnamed module of loader 'app')
How can I find all those classes?
Sample structure
class A extends B {}
class B implements C {}
#AnnotationD
interface C {}
#Immutable
#interface AnnotationD {}
I want to find class A and B because they are assignable to classes meta-annotated with #Immutable.

This should work:
#ArchTest
final static ArchRule rule = ArchRuleDefinition.classes()
.that().areMetaAnnotatedWith(Immutable.class)
.or().areAssignableTo(CanBeAnnotated.Predicates.metaAnnotatedWith(Immutable.class))
.should(...)
It applies the rule to all classes that are meta-annnotated with #Immutable or that extend/implement a class/interface that itself is annotameta-annotated with #Immutable.
If you require more flexibility, you can also define your own predicates to select the relevant classes, e.g.:
#ArchTest
static ArchRule rule = ArchRuleDefinition.classes()
.that().areMetaAnnotatedWith(nameEndsWith("Immutable"))
.or().areAssignableTo(CanBeAnnotated.Predicates.metaAnnotatedWith(nameEndsWith("Immutable")))
.should(...);
private static DescribedPredicate<JavaAnnotation<?>> nameEndsWith(final String suffix) {
return DescribedPredicate.describe(
"annotation name ending with " + suffix,
javaAnnotation -> javaAnnotation.getRawType().getSimpleName().endsWith(suffix));
}

Related

No ClassTag Avaliable for Trait / Abstract Class

Consider the following trait:
trait Aggregatable[Command] {
protected[aggregator] type ActorReply
protected[aggregator] val actorReplyClassTag: ClassTag[ActorReply]
... // Additional Implementation
}
then, the following abstract class:
abstract class AsyncWorker[Request, Reply] extends Aggregatable[AsyncWorkerRequest[Request, Reply]] {
override final type ActorReply = AsyncWorkerReply[Request, Reply]
override protected val actorReplyClassTag: ClassTag[AsyncWorkerReply[Request, Reply]] = ???
... // Additional Implementation
}
and then the concrete implementation:
class SiteCategoriesExtractorWorker extends AsyncWorker[SiteCategoriesRequest, SiteCategoriesReply]
The problem is that I cannot initialize actorReplyClassTag properly.
The desired solution should:
SiteCategoriesExtractorWorker should not be aware of actorReplyClassTag
type ActorReply is used on aggregator package as asInstanceOf[ActorReply]
actorReplyClassTag is used on messageAdapter (https://doc.akka.io/japi/akka/current/akka/actor/typed/scaladsl/ActorContext.html#messageAdapter(scala.Function1,scala.reflect.ClassTag)
Aggregatable is preferred to be a trait rather then abstract class
Note: I'm using reflection in order to make some generic aggregation over Aggregatable interface.
Any ideas how to achieve this?
You just need to pass class tags of the parameters down to AsyncWorker, then class tag will be available implicitly:
class AsyncWorker[Request : ClassTag, Reply : ClassTag] extends Aggregatable[AsyncWorkerRequest[Request, Reply]] {
type ActorReply = AsyncWorkerReply[Request, Reply]
val actorReplyClassTag: ClassTag[ActorReply] = implicitly[ClassTag[ActorReply]]
}

HazelcastSerializationException after moving class to a different package

I am running an embedded hazelcast deployment and storing a ConcurrentMap<String, MyType>, where the type of value in the map is my custom class.
MyType
public class MyType implements Serializable {
private MyTag tag;
...
}
One of its fields is an interface MyTag.
MyTag
public interface MyTag<T> {
}
And I have a class containing several enum implementations of MyTag interface:
MyTags
public class MyTags {
public static enum Integers implements MyTag<Integer> {
INT_TAG1,
INT_TAG2,
...
}
public static enum Strings implements MyTag<String> {
STRING_TAG1,
...
}
...
}
After moving MyTags class to a different package and redeploying one of my services (with MyType in the new package) upon attempting a get on the map, an exception is thrown:
com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassNotFoundException: old.package.MyTags$Strings
How could I protect myself from this situation when deploying on a production environment?
Java's Serializable depends on the class remaining the exact same. A moved class is no longer the same class. Select one of the other options that Hazelcast has for serialization of objects. See Comparing Serialization Options for some more guidance on the different options.

Is it possible to get a class by qualifier annotation using reflection?

I have an interface with many possible implementations. The right implementation should be chosen at the runtime. And so Reflection sounds to be the solution.
I have annotated these classes by a qualifier that has as argument an enumeration.
So, is it possible to get at runtime using reflection the right implementatoin class by passing the right enumeration to the annotation?
But, reflection is not mandatory if there is another way..
First, here it is the enumeration :
public enum CATEGORY {
A,B,C;
}
Then, here it the interface :
public interface GenericI{
void method1(CATEGORY arg);
// some other methods
}
And now, here there are the annotated implementations :
#MyAnnotation(CATEGORY.A)
public class impl1 implements GenericI{
void method1(CATEGORY arg){
// some work here
}
}
#MyAnnotation(CATEGORY.B)
public class impl2 implements GenericI{
void method1(CATEGORY arg){
// some work here
}
}
Finally, the proxy that at a way, select dynamically the right implementation using annotation and enumeration (probably it shouldn't implement GenericI ??):
public class MyProxy implements GenericI {
// Here we must be able to select the right implementation
}
Reflexion is an answer, but you need to get all the classes from the classpath, and examinate it to find the implementation of your interface.
You can use this reflection library and get all the implementations like this (if your interface name is MyInterface):
Reflections reflections = new Reflections("your.base.package", new SubTypesScanner(), new TypeAnnotationsScanner());
Set<Class<T extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);
for (Class<T extends MyInterface> c : classes) {
check if c is the rigth implementation!.
}
If you don't want to use a external library, you can use the Java Reflection API, and scan all packages, somethis like (see this answers to use instrumentation):
Instrumentation inst = InstrumentHook.getInstrumentation();
for (Class<?> c: inst.getAllLoadedClasses()) {
if (MyInterface.class.isAssignableFrom(c)) {
check if c is the rigth implementation!.
}
}
The first option allow you to save the Reflections object as a xml, so the component scan is saved and it's done only one time.
To check if the clazz have a Qualifier you can use:
if (c.isAnnotationPresent(Qualifier.class)) {
bingo!.
}
or is a property of the annotation:
if (c.isAnnotationPresent(Qualifier.class)) {
Qualifier q = c.getAnnotation(Qualifier.class);
if (q.theRight()) {
bingo!
}
}
I recommend you to see if the FactoryProblem is applycable to your problem, choose always Factory instead of Reflection.
An example "proxy":
public class MyProxy implements GenericI {
Map<Category, GenericI> generics;
public MyProxy() {
Reflections reflections = new Reflections("your.base.package", new SubTypesScanner(), new TypeAnnotationsScanner());
Set<Class<T extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);
generics = new HashMap<Category, GenericI>();
for (Class<T extends MyInterface> c : classes) {
map.put(c.getAnnotation(MyAnnotation.class).value(), c.newInstance());
}
}
void method1(CATEGORY arg){
map.get(arg).method1(arg);
}
}
This is extremely heavy and overcomplicated, if you use this, please add extensive test, and make MyProxy a Singleton.
If you use a IOC framework:
#Component
public class MyProxy implements GenericI {
#Autoriwed // If spring
List<GenericI> generics;
#Inject #Any // If CDI
private Instance<GenericI> services;
Map<Category, GenericI> generics;
#PostConstruct
void makeMap() {
generics = new HashMap<>();
for (GenericI component : generics) {
generics.put(
component.getClass().getAnnotation(MyAnnotation.class).value(),
component);
}
}
void method1(CATEGORY arg){
map.get(arg).method1(arg);
}
}
I assume you don't know al possible subclasses.

Is this the correct way of translating Java interface into Scala?

I am starting to learn Scala and I will do a simple cross compiler.
I will support a small set of instructions like print.
Note: the code snippets are not tested or compiled.
Here is what I would do in JAVA.
public interface Compiler{
String getPrintInstruction();
}
public class JavaCompiler implements Compiler{
public String getPrintInstruction(){
return "System.out.print(arg0);"
}
}
public class ScalaCompiler implements Compiler{
public String getPrintInstruction(){
return "print(arg0);"
}
}
Is the snippet below the correct "Scala way"?
trait Compiler {
var printInstruction: String
}
class JavaCompiler extends Compiler {
var printInstruction = "System.out.print(arg0);"
}
class ScalaCompiler extends Compiler {
var printInstruction = "print(arg0);"
}
EDIT:
I will move my second question to a new thread.
For a 1:1 mapping, those vars should be changed to defs.
trait Compiler {
def printInstruction: String
}
class JavaCompiler extends Compiler {
def printInstruction = "System.out.print(arg0);"
}
class ScalaCompiler extends Compiler {
def printInstruction = "print(arg0);"
}
def declares a method. When you don't provide an implementation, it becomes an abstract method.
EDIT:
The technique used here is a valid and useful technique. Alternatively you could use one of the following two techniques to model your problem.
1) Discriminated unions. (aka sum types.)
Refer to this excellent article to learn about this concept. This is how your example would probably look like when modeled this way:
sealed trait Compiler {
def printInstruction: String = this match {
case JavaCompiler => "System.out.print(arg0);"
case ScalaCompiler => "print(arg0);"
}
}
case object JavaCompiler extends Compiler
case object ScalaCompiler extends Compiler
2) Type class pattern.
Here is a great post by Daniel Sobral on this topic. You can dig up a few more by googling the terms type-class, pattern, Scala, implicits etc. This is how your code might look like if the problem's modeled with type class pattern:
trait Compiler[C] {
def printInstruction(c: C): String
}
case object JavaCompiler
implicit object JavaCompilerIsCompiler extends Compiler[JavaCompiler.type] {
def printInstruction(c: JavaCompiler.type): String = "System.out.print(arg0);"
}
case object ScalaCompiler
implicit object ScalaCompilerIsCompiler extends Compiler[ScalaCompiler.type] {
def printInstruction(c: ScalaCompiler.type) = "print(arg0);"
}
For your problem, the original approach and the discriminated unions approach seem to be the best modeling solutions.
The most idiomatic way is to use a def for abstract properties, and a val for concrete read-only properties. Under the Uniform Access Principle, a val can be used to implement a method:
trait Compiler {
def printInstruction: String
}
class JavaCompiler extends Compiler {
val printInstruction = "System.out.print(arg0);"
}
class ScalaCompiler extends Compiler {
val printInstruction = "print(arg0);"
}
Why do I have to re declare the variable one more time in the class when I have declared it in the trait?
Because you declared the signature of the method printInstruction but you did not say what it did. In a class, as it is not an abstract class all functions should be defined.
By the way, you could have defined printInstruction directly in the trait Compilerif it is supposed to do the same in every implementation.

#XmlSeeAlso alternative

I have the following:
class A{
#XmlElement
String name;
//getters and setters
}
and
class B extends A{
#XmlElement
String height;
//getters and setters
}
finally I have
#XmlRootElement
class P{
#XmlElement
List<A> things;
//getters and setters
}
If I do
List<A> l = new ArrayList<A>();
l.add(new B('hello', 20)) //Add new B with height of 20 and name hello
P p = new P();
p.setThings(l); //Set things to list of B's.
and marshal P, I only get the field as part of things and not height.
I know that I can add #XmlSeeAlso(B.class) in A and it will all work.
But the issue is that I don't know all extended classes other than B, as A may be extended on runtime.
How do I dynamically define #XmlSeeAlso on runtime?
This depends on how you are creating your JAXBContext. The newInstance method can be called with an explicit list of all your classes, the documentation for that method also gives a similar example.
The client application must supply a list of classes that the new context object needs to recognize. Not only the new context will recognize all the classes specified, but it will also recognize any classes that are directly/indirectly referenced statically from the specified classes. Subclasses of referenced classes nor #XmlTransient referenced classes are not registered with JAXBContext. For example, in the following Java code, if you do newInstance(Foo.class), the newly created JAXBContext will recognize both Foo and Bar, but not Zot or FooBar:
class Foo {
#XmlTransient FooBar c;
Bar b;
}
class Bar { int x; }
class Zot extends Bar { int y; }
class FooBar { }
Edit: If you know at least the package names of potential jaxb classes you could also create a context given a context path.
If the above is not possible you could also create the list of classes at runtime, based on the object you want to serialize. I think it would be better to try to refactor your code to make this unnecessary. The code below is untested:
Set<Class> classes = new HashSet<Class>();
classes.add(p.getClass());
for (A a : p.getThings()) {
classes.add(a.getClass());
}
JAXBContext context = JAXBContext.newInstance(classes.toArray(new Class[classes.size()]));
Note that #XmlSeeAlsocan also be annotated on a web service, see this post: http://weblogs.java.net/blog/kohlert/archive/2006/10/jaxws_and_type.html
This is useful if your base class doesn't have access to the subclasses (e.g. because they're in a different module), but your web service has.

Categories