Can I use custom annotations to classify Java classes? - java

Is it possible that use self defined Annotation to classify java class into different product function ? (Following are my thoughts)
If not, are there any other method to achieve the same purpose in Android project?
Step1: use self defined annotation to make clear java class's function
#SelfDefinedAnnotation( "product-function-a" )
class MyClass {
void func() {
//do something
}
}
Step2: during building period, generate a mapping file like this
MyClass -> product-function-a
YourClass -> product-function-b

I'm not sure about android (never worked with it), but in pure java its possible for sure.
You should define an annotation with retention policy SOURCE and since you're talking about build time, define an annotation processor. This is something that is "hooked" into the compilation process and allows creating such a mapping (I assume you want to store it in some kind of file, maybe *.properties file, or even generate a java source code with these definitions.
The annotation processor is broad topic, there are many ways to register them, so it pretty much depends on how do you build your stuff exactly, but its a general direction.
Please check out this tutorial it talks about annotation processors, the ways to register them, to associate with your custom annotation and so forth.
One suggestion though, if you're about to generate Java Source class and not just a properties file, this tutorial goes "low level" and tries to prepare the syntax by itself, I suggest using a much nicer (IMO) Java Poet library that will help to generate a proper java code

Related

Using an Annotation Processor to create a list of classes with a certain annotation

I have a custom annotation that I've implemented and I'd like to use an annotation processor to generate a list of all the classes in my app that use that particular annotation.
I've found this tutorial which describes how to generate a class file using an annotation processor, so it should be quite easy to generate a class for each class with my annotation.
What I can't figure out is how I can collect all of that information into a single class. There doesn't seem to be a way to modify a class, so I can't append new items to the list once the class has been generated the first time.
Is there a way to use an annotation processor to generate a method that will return the list of all classes in an app that are annotated with a particular annotation?
Generated classes do not necessarily have to correspond one-to-one to the input classes being processed. Plus, you can search for classes (Elements) that are annotated with a given annotation via the RoundEnvironment:
roundEnvironment.getElementsAnnotatedWith(MyAnnotation.class)
From this you can generate a single class with a method that returns a collection of the classes found.
A couple issues around this to highlight:
Annotation processors can run along with other annotation processors and thus have to deal with classes generated at compile time. To aid this, Java annotation processing is performed in rounds to allow processors to catch the outputs of others. To be compatible with other processors you need to gracefully handle the ErrorType.
Only classes in the current compilation pass are returned from the RoundEnvironmnet methods so classes in external libraries will not be included.
IDEs (cough cough Eclipse) implement the annotation processing facilities of Java differently which can be a problem for processors that require a full non-partial compilation like I've described.
Coincidentally, I created a similar project recently that does what you are looking for:
https://github.com/johncarl81/silver
Silver is very much a WIP and uses a lot of library code to accomplish the task, but it may give you an idea for what's possible.

Determine Disk Geometry on Windows using JNA

Could someone please advise on how to get Disk_Geometry in JNA.
I know this is straight forward in C++ by creating a handle for a disk using CreateFile(), using Deviceiocontrol to query it and using DISK_GEOMETRY to get different disk attributes. I would like to be able to do the same thing in Java using JNA, but DISK_GEOMETRY type is missing in the Kernel32.
Please help.
You can easily extend the interface definitions provided with JNA to add anything that's "missing". You can add any function, structure or constant definitions that suit your purpose.
public interface MyKernel32 extends Kernel32 {
public class DISK_GEOMETRY extends Structure {
// Fill in specifics of the structure here, following the type mapping rules
// in the JNA documentation, or use [JNAerator][1] to auto-generate the mapping.
}
}
I do not know how to do this with JNA but would like to suggest you to use WMI instead. The WMI class [Win32_DiskDrive][1] seems to be a good candidate for you. It contains what you need and probably even more. Now the question is "how to call WMI from java?" There are number of ways. The simplest one is to write script using JScript or VBS and call it from java using ProcessBuilder. This way is simple and does not require dealing with native code and external libraries but could be a little bit slow because process-to-process communication is used.
Other way is to use one of available java-to-com packages. For example JaWin, JInterop, JIntegra.

Dependency Injection With Annotations

I would like to build my own custom DI framework based on Java annotations and I need a little direction to get started. I know it would be much easier to use one of the many wonderful frameworks out there such as guice or spring, but for the sake of my own curiosity, i'd like to build my own.
I'm not very familiar with annotations, so i'm having a bit of trouble finding resources and would really appreciate someone just sort of spelling out a few of the steps i'll need to take to get started.
As fore mentioned, id like to take a factory approach and somehow label my getters with an #Resource or #Injectable type annotation, and then in my business classes be able to set my variable dependencies with an #Inject annotation and have the resource automatically available.
Does anyone have any sort of resource they can pass along to help me understand the process of tagging methods based on annotations and then retrieving values from a separate class based on an annotation. A little direction is all I need, something to get me started. And of course i'll be happy to post a little code sample here once I get going, for the sake of others future reading of course.
EDIT
The resources I am using to put this together:
Java Reflection: Annotations
How to find annotations in a given package: Stack Overflow ?
Scanning Annotations at Runtime
I have not actually finished writing this yet, but the basic task list is going to be as follows (for anyone who might be interested in doing something similar in the future)
At class runtime scan for all #Inject fields and get object type.
Scan all classes (or just a specific package of classes (I haven't
decided yet)) for annotated methods #InjectableResource.
Loop all annotated methods and find the method that returns the
object type I am looking for.
Run the method and get the dependency.
It will also be helpful to note that when scanning all the classes I will be using a library called Javassist. Basically what this does is allows me to read the bytecode information of each class without actually loading the class. So I can read the annotation strings without creating serious memory problems.
Interesting that you want to build your own. I love Google Guice - it makes code so elegant and simple.
I've used this guide before which I found pretty useful for learning about annotations and how you can pull them out of classes and methods.
You will have to define your own Annotations which is done using #interface. Then you will have to define some kind of class for doing bindings e.g. where you see an interface bind in this concrete class. Finally, you will need some logic to pull it altogether e.g. go through each class, find each annotation, and then find a suitable binding.
Give consideration to things like lazy instantiation through Reflections and singletons. Guice, for example, allows you to use a singleton so your only using one instance of the concrete class, or you can bind a new version each time.
Good luck!
Have a look at the following methods:
java/lang/Class.html#getAnnotation(java.lang.Class)
java/lang/Class.html#getAnnotations()
java/lang/Class.html#getDeclaredAnnotations()
Methods of the same name also exist for the java/lang/reflect/Method, java/lang/reflect/Field and java/lang/reflect/Constructor classes.
So in order to use these sorts of methods, you need to know a bit about Java reflection.

DLLs for a dynamic Java program?

I'm currently working on a Java project where I have a set of data which I wish to output in several custom formats. I have a class for each format, which takes the raw data and converts it accordingly. However, to begin with I am only implementing two or three of these formats, but wish to allow more formats to be added at a later date without having to do a massive rebuild of the application.
My idea was to create a DLL for each of the format classes, and have my application pass the data to be converted to each of these. This way, I can create a DLL later on and have my main application accessing it. (I would gladly listen to any alternative ways of doing this, as someone who has done this in C++/C# before this felt like the logical solution but it may not be applicable to Java)
My problem is that I have absolutely no idea how to do this - in C++/C# I could write this in a few lines of code but I'm not sure how it works with Java. At the risk of asking a terribly vague question, how can I do this?
Answers are greatly appreciated and cookies and tea will be offered. :)
Thanks in advance,
M
Edit: Sorry, just to add: I am also unsure how to create the DLL, which must be in Java for this project, to be read in the first place. Thanks. :)
Rather than using a DLL per se, it seems like what is wanted is a plugin architecture of some sort.
One reason why I wouldn't recommend using a DLL unless it is necessary is that linking Java code with native code will require using the Java Native Interface (JNI) which would probably require more effort than a pure Java solution.
One relatively simple way to do so is to use the reflection capabilities of Java.
From the information given, I would probably go along the lines of the following:
Define an interface for the output format.
Create a Java class implementing the interface.
Have the class available from the classpath.
Dynamically load the class using reflection. (Using the Class.newInstance method can instantiate objects from class files loaded by the ClassLoader.)
With these steps, it would be possible to implement a simplistic plugin which wouldn't require a full rebuild when support for a new format is required.
Step 1: Define the interface
Let's say we end up with an interface like the following:
public interface Outputter {
public void write(Data d);
}
Step 2: Make an implementation class
Then, we'll make an implementation class.
public class TextOutputter {
public void write(Data d) {
// ... output data to text
}
}
Then, compiling the above, we'll end up with a class file called TextOutputter.class.
Step 3: Make the class available from the classpath
When running the main application, we'll need to have the above TextOutputter.class in the classpath. Normally, one would tell the JVM a list of places to consider as the classpath, and that should include the above class file.
Once that is done, we should be able to load the above class using reflection.
Step 4: Dynamically load the class using reflection
Now, when we actually want to load the above class, we'd do something like the following:
// Note: We load the class by specifying the fully-qualified class name!
Class<?> clazz = Class.forName("TextOutputter");
// Then, we instantiate the class.
// Note that the following method will call the no-argument constructor.
Outputter outputter = clazz.newInstance();
// Now, we can give data to the TextOutputter object that we loaded dynamically.
outputter.write(...);
The Class.forName method is used to attempt to find the TextOutputter class from the default ClassLoader. Once we obtain the class as a Class representation, we can then instantiate an object of that class.
Instantiating the object can be performed by using the Class.newInstance method. If something other than the no-argument constructor should be used, the Constructor of the class would have to be obtained proceed to instantiate the object from there.
The object instantiates via reflection is then placed into a Outputter variable, so the write method can be called on the TextOutputter.
Adding more formats would entail the above process, but changing the fully-qualified class name (e.g. for String, the FQCN is java.lang.String) is all that is needed to load up a different class.
In a nutshell, that's what it will take to dynamically load class files and use it from your application.
(Just as a side note, I did not actually compile the above code, so there may be some errors here and there, but I hope I could illustrate the process it will take.)
I've made such things.
i created an open java based plugin architecture POJO based,that even did reload on the fly of updated plugin classes.
JNI is the interface for dealing with native code.
The only technical part was to rewrite a classloader that enabled DLL reloading dynamically at runtime.
But if you do only make "offline" updates, no such things are needed.
You can load a new DLL at any time with System.loadLibrary(). However you may need to load a java class for it to bind to.
You might find using an OSGi container helpful as this supports both load and unloading of modules (including shared libraries)
I would suggest using karaf with iPOJO but there are many others.
If you want write native codes (compiled to a DLL) to be used in java, you want to look at Java Native Interface (JNI).
Update you can use System.loadLibrary(String libName) (if you know the library name and the library path is set) or System.load(String filename) (library filename) to load library (DLL) in java.
I think you can ignore the JNI path. I have the impression you're using the term dll for lack of a better word, you don't really need a dll.
You could do the same thing in Java, but you'd put your filters in jar files instead of dll.
Define an interface for the file format filters to implement
Put each implementation into a jar, in a specific folder (like 'filters')
At one point in the app, iterate over the folder, generate classloader for the jars
Use reflection to find all implementations of your interface, and create a class for each
Call the methods to do their job
That's basically it.
Java SE 6 introduces the ServiceLoader class:
http://download.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html
If you want a proper modular approach consider the NetBeans Platform (especially if it is a desktop application) or OSGi.

How can I extend Java code generated by JAXB, CXF or Hibernate tools?

With generated Java source code, like
code generated with Hibernate tools
code generated with JAXB schema binding (xjc)
code generated with WDSL2Java (cxf)
all generated classes are "value object" types, without business logic. And if I add methods to the generated source code, I will loose these methods if I repeat the source code generation.
Do these Java code generation tools offer ways to "extend" the generated code?
For example,
to override the ToString method (for logging)
to implement the visitor pattern (for data analysis / validation)
For JAXB, see Adding Behaviours.
Basically, you configure JAXB to return a custom instance of the object you'd normally expect. In the below example you create a new object PersonEx which extends the JAXB object Person. This mechanism works well in that you're deriving from the generated classes, and not altering the JAXB classes or schemas at all.
package org.acme.foo.impl;
class PersonEx extends Person {
#Override
public void setName(String name) {
if(name.length()<3) throw new IllegalArgumentException();
super.setName(name);
}
}
#XmlRegistry
class ObjectFactoryEx extends ObjectFactory {
#Override
Person createPerson() {
return new PersonEx();
}
}
Note that the #Override directive is important in case your JAXB object changes - it will prevent your customisation becoming orphaned.
As for Hibernate you may tweak the template files used in code generation to change their behaviour. If you want to tweak the HIbernate Tools you can edit, for example: dao/daohome.ftl
You may even add fields to the "toString()" output editing the .hbm.xml files
...
<property name="note" type="string">
<meta attribute="use-in-tostring">true</meta>
<column name="note" />
</property>
...
Both for logging and validation you may consider using AOP with AspectJ (I don't recommend messing with the generated code, since you might want to build that from scratch many times over).
First I would reiterate that modification of generated code has many problems associated with it and that, where possible it should be avoided. That said sometimes this is impractical to avoid or more effort than just dealing with the changes when the code is regenerated.
Sadly java doesn't support the concept of partial classes that c# has. These are precisely to solve this sort of problem.
You should see if your code generation tools support some form of meaningful comments which delimit regions added by yourself in the class (this is unlikely and won't help if you are modifying the code rather than adding to it)
You best option if you really wish to do this is to generate the files initially but check them into a version control repository immediately.
Then make your changes, check that in.
Next time you rerun the tools and let them overwrite the existing files you can diff against your source controlled ones and merge the changes back in (most trivial changes like addition of new columns/tables will be little effort.
This will not help you as much if the code generator suddenly generates radically different code (say a new version) but in those cases any code you added which wasn't simply additional convenience methods relying on data/methods already exposed publicly) will have problems no matter how it is mixed into the class. The version control system does still help however since it also records the original changes so you can see what you had added previously and what, one would assume, you need to recreate in the new style.
It is not a good idea to edit generated code files, either by editing the files them selves or by subclassing. Whatever you do, be sure to leave the signature created by the tool intact, so that it will be possible to understand in the future that the file was auto-generated.
I recommend that you research the command options of the tools to see if they allow you some flexibility. Some tools can generate abstract classes or interfaces instead of concrete classes. If this is not possible, create a domain object that includes the autogenerated object as a member variable.
The way I have used Hibernate is to generate base classes that I then extend. I add all my business logic (if any) to these subclasses. I quite often also end up changing the FreeMarker templates used by Hibernate to further customize the generated classes.
The AOP citation is a good one. I'll add Spring, which has very nice AOP features built in.
Have a look at
http://code.google.com/p/jaxb-method-inserter/
Its a small plugin for JAXB I wrote, Its quite simple to uses. Hope it help

Categories