If you’ll be in Warsaw this weekend, and if you speak polish, be sure not to miss Javarsovia, a one-day conference organized by the Warsaw JUG. I am giving a talk there about how you can use annotations together with static analysis to find bugs in your program early (first presentation in the 3rd track, 9:45, room 103B). Among other things, I’ll be demoing the static access detector and the typestate checker.
See you there!
Adam
Post to del.icio.us
If you’ll be attending Jazoon next week, be sure not to miss the Envers presentation! It will take place on Wednesday (24th July), at 4pm (here are the presentation details). I’ll be attending the whole Jazoon conference, so if you’d like to talk about Envers (or anything else :) ), just catch me there.
See you in Zurich!
Adam
Post to del.icio.us
Yesterday I uploaded a new release of Envers, 1.2.1.GA. It is mainly a bugfix release, but there is also one new feature. You can now access the current revision entity directly using AuditReader, without the need to use a revisions listener. For details, see the description of the AuditReader.getCurrentRevision() method in the javadocs.
You can see the list of issues closed in jira.
The release is available for download here; it’s also in jboss’s maven2 repository.
Have fun! :)
Adam
Post to del.icio.us
The StaticAccess detector is a FindBugs plugin, which lets you verify that methods do not rely on static (global) state, that is, that they don’t read or write static variables which aren’t constant. This can be useful for example when writing concurrent programs (which should use as little global state as possible) or “pure” functions (I’ll write about that in another post).
You can specify that a method shouldn’t rely on global state using the @StaticIndependent annotation. Such methods will be checked by the detector included in the plugin, if they don’t read or write static variables, or call non-static-independent methods.
For example, running FindBugs with the StaticAccess plugin on the following code:
import pl.net.mamut.staticaccess.StaticIndependent;
public class StaticIndependentExample {
public static Integer globalInt = 10;
public static final Integer CONSTANT = 12;
// This method is annotated as static-independent,
// that is, cannot rely on static (global) state
@StaticIndependent
public void testStaticIndepdendent() {
// line 12
int local = globalInt;
// line 14
globalInt = 11;
// line 17
int local2 = CONSTANT;
}
// Unannotated methods aren't checked
public void testStaticDependent() {
// line 23
int local = globalInt;
}
}
will report errors on lines 12 and 14, but won’t report errors on line 17 (accessing a constant which can’t change) or line 23 (the method isn’t annotated with @StaticIndependent).
You can annotate all methods in a class or package by default as static independent using FindBugs’s @DefaultAnnotationForMethods meta-annotation, and later override that for selected methods using @StaticDependent.
All methods from the java.lang package are static-independent by default, and only String and primitive types wrapper classes are treated as constants when declared as static final fields. This list should be certainly expanded, so if you’ve got good candidates, write or send a patch!
For information on installation, downloads and usage see the webpage. You can find the jars there; they are also available in maven, and the source code on github.
Have fun!
Adam
Post to del.icio.us
I’ve uploaded a new version (0.2) of the typestate checker (for an introduction, see this blog post), which contains bug fixes and much improved exception handling. The binaries, source code and installation instructions are on the web page; the source code is also on github, and the binaries in the maven repository. You can use the typestate checker with the jsr308-maven plugin.
A new state-annotation element: onException is supported, which specifies the state, to which an object transits, in case of an exception being thrown (from the place where the object is used: a method or constructor). For example, the specification of some of InputStreams methods could look like this:
class InputStream implements Closeable {
int read() /*@Open(onException=InputStreamError.class)*/
throws java.io.IOException;
close() /*@Any(after=Closed.class)*/
}
This specification says that the read method can only be invoked when the object is in the “open” state, and in case of an error, the object transits to the “inputStreamError” state; that means that the read method cannot be invoked anymore. The close method transits the object from any state (so it can be invoked both when the stream is open, or in an error), to a closed state; again, read cannot be invoked anymore.
The annotations are in comments to make the code Java5-compatible; the checkers framework will recognize them.
Thanks to such specification, and the typestate checker, we can verify at compile-time that no read operations are invoked when the stream is closed. For example, the code below won’t compile (type-check), if compiled with the typestate checker, because of the invalid use of the last read method:
int test(@Open InputStream stream) throws IOException {
int ret = 0;
try {
int input;
while ((input = stream.read()) != -1) {
ret += input;
}
} finally {
stream.close();
}
// An error will be reported here; the stream is closed
ret += stream.read();
return ret;
}
More examples can be found in the examples directory of the source distribution (and ran with the example.sh script; on github: example 1, example 2)
The flow algorithm was improved to properly handle various try-catch-finally combinations, inferring the states of the objects properly when the catches are “alive” or “dead” (if they return/throw an exception or not).
Any opinions, comments, suggestions are welcome! :)
Adam
Post to del.icio.us
The recently released Envers 1.2.0.GA finally made it to the JBoss Maven repository; you can find it here:
http://repository.jboss.org/maven2/org/jboss/envers/jboss-envers/1.2.0.GA-hibernate-3.3/
Also, following Bob’s example, I’ve put the JSR 308 typestate checker and Maven2 plugin on github:
So everyone can now easily grab the source code and modify it.
Have fun!
Adam
Post to del.icio.us
Today Envers 1.2.0.GA has been released! It is a Hibernate 3.3 compatible version of the newest Envers codebase, which will be included as a module in Hibernate 3.5. You can download it here, and find documentation here.
The main highlights of this release are:
@Versioned becomes @Audited etcFor a full list of issues solved, see here. Special thanks to Erik-Berndt Scheper for providing valuable patches!
The release will also be soon available through the JBoss maven repository.
Have fun,
Adam
Post to del.icio.us
I’ve written a prototype JSR308 Checkers Maven2 plugin. You can use the plugin to run any checker on the sources of your module(s).
The JSR308 compiler, and in effect also the checkers, are run in a separate, forked, JVM process. Additionally, this process only does the processing, without actual compilation. So all of your files will be compiled by the same javac as before. The plugin only runs the additional verification of the source code, and will not affect the produced bytecode. Java6 is required to run the forked JVM.
You can easily try using the standard checkers, for checking nullness, interning and mutability errors, as well as the typestate checker; I’ve uploaded the necessary jars to my repository, so to use any of them, you’ll need first to add repositories to your pom.xml:
<repositories>
<repository>
<id>mamut-releases</id>
<url>http://repository.mamut.net.pl/content/repositories/releases</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>mamut-releases</id>
<url>http://repository.mamut.net.pl/content/repositories/releases</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
Then, to use the annotations used by the standard checkers, you’ll have to declare a dependency:
<dependencies>
<!-- annotations for the standard checkers: nullness, interning, mutability -->
<dependency>
<groupId>mamut.net.pl</groupId>
<artifactId>checkers-quals</artifactId>
<version>0.8.6</version>
</dependency>
<!-- and if you want to use the typestate checker: -->
<dependency>
<groupId>mamut.net.pl</groupId>
<artifactId>typestate-checker</artifactId>
<version>0.1</version>
</dependency>
<!-- other dependencies -->
</dependencies>
And finally, you need to attach the plugin to your build lifecycle:
<build>
<plugins>
<plugin>
<groupId>mamut.net.pl</groupId>
<artifactId>checkersplugin</artifactId>
<version>0.1</version>
<executions>
<execution>
<!-- run the checkers after compilation; this can also be any later phase -->
<phase>process-classes</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- checkers you want to be run -->
<processors>
<processor>checkers.nullness.NullnessChecker</processor>
<processor>checkers.interning.InterningChecker</processor>
<processor>checkers.typestate.TypestateChecker</processor>
</processors>
<!-- other configuration - see webpage for details -->
</configuration>
</plugin>
</plugins>
</build>
And that’s it! After compiling, the specified checkers (annotations processors) will be run on your source code and report any errors found.
For more information and full configuration options description, see the web page: http://www.warski.org/checkersplugin.html
Waiting for feedback :)
Adam
Post to del.icio.us
December came, so it’s time for Devoxx! (formerly JavaPolis)
If you are planning to visit Antwerp this year, make sure to come and see the Envers presentation (first conference day, 3pm)! I will explain the basic concepts, how to use various parts of the library as well as show some use-cases. Also, if you have any questions or suggestions, it will be a great opportunity to meet :).
As you may already know, Envers is now a Hibernate core module. There is no official Hibernate release yet available with Envers included, but I’ve uploaded a preview jar, which will work fine with Hibernate 3.3.x. The migrated documentation is also avialable in html and pdf formats on the site. If you spot any errors, or find some information missing, please let me know! For Maven2 users, a snapshot of Hibernate-3.4.0 (which includes Envers) is deployed to the jboss snapshots repository (located here, instructions here).
Main changes in this preview release:
@Audited instead of @Versioned etc.As always, waiting for feedback on the forums!
Enjoy! :)
Adam
Post to del.icio.us
When dealing with mutable objects in Java, we quite often see that “states” of the class considered emerge. The (abstract) “state” depends of course on the content of the fields of the object. When methods are invoked, which mutate the fields, the state of the object may change. Also, it may be illegal to call some methods in one state, but legal in another.
So far, specifying the state space of an object, which methods can be called in which states, and how methods change the state, is done mainly in comments (javadocs). With the new possibilities brought by JSR 308 - type annotations, it’s now possible to do it in a much more structured way.
The basic idea is simple. Each state of our object is one annotation. We can define those annotations for example as inner classes. There are 2 immediate gains:
As an example, let’s assume that we have a class for reading a remote resource, for example RemoteResourceReader. Objects of this class can be in one of the three states:
The inital state is configuration, in which we set the connection properties, like the URL, username, password, etc. Then, we can change the state to open, read some data, and close the connection, changing the state to closed. After that, we may re-open the connection to read more data, etc.
So how would the source of our class look like? First, we define the states:
public class RemoteResourceReader {
/** Connection to the resource is being configured */
public static @interface Configuration { }
/** Connection to the resource is open, data can be read */
public static @interface Open { }
/** Connection to the resource is closed, data cannot be read */
public static @interface Closed { }
(...)
}
Now, we have to specify what is the initial state and how methods change the state. Thanks to JSR 308, that is easy. Type annotations extend the number of places, where annotations are allowed; you may place them on any type. See its web page for more information.
One of the new places, where annotations are allowed, is the “method receiver”. This lets you specify meta-data (annotations) that apply to the object, on which the method is called. For example, we want to specify that the read method can be invoked on an object only when it is in the open state; similarly, the setURL method can be invoked only when the object is in the configuration state. Using JSR308, we can write it like this:
(...)
public String read() @Open { ... }
public void setURL(String newURL) @Configuration { ... }
(...)
However, to keep the code compatible with Java 5/6, we may place the annotations in comments. They will still be recognized by the JSR308 checker framework (why this is important - read on :) ).
Finally, what about state changes? Here, we also use the method receiver annotations. We may add an element to our state annotations, which will specify the state of the object after the method invocation. For example:
(...)
public void open() @Configuration(after=Open.class)
@Closed(after=Open.class) { ... }
public void close() @Open(after=Closed.class) { ... }
(...)
We have specified that:
open method, if the object was in the configuration or closed states. After invoking this method, the object will be in the open stateclose method, only if the object was in the open state. After invoking this method, the object will be in the closed stateWhat are the benefits of using state annotations so far? Improved documentation: users immediately see in what states objects of the class can be, when it is legal to call a method and how the states change. However, there is more: you can check if your objects are in the correct state by using the typestate checker!
The typestate checker is built on top of the checkers framework, which out-of-the box provides other very useful checkers, for nullness and immutability. Be sure to try them out :).
To use the typestate checker, go here for downloads and installation instructions. The only additional requirement is that you must annotate your state annotations with @State. The checker will verify, using flow analysis, if you invoke methods on objects in the correct state, pass parameters in the correct state etc. This version of the checker should be treated more like a proof-of-concept, than as a final version. It is in a very early development stage, so your comments and experiences are very welcome! :)
To complete the RemoteResourceReader example, here is a full version of the class, ready to be used with the typestate checker:
public class RemoteResourceReader {
/** Connection to the resource is being configured */
@State public static @interface Configuration {
Class<?> after default Object.class }
/** Connection to the resource is open, data can be read */
@State public static @interface Open {
Class<?> after default Object.class }
/** Connection to the resource is closed, data cannot be read */
@State public static @interface Closed {
Class<?> after default Object.class }
// Initial state of the object - specified in the
// constructor's receiver annotation
public RemoteResourceReader() /*@Configuration*/ { ... }
public void setURL(String newURL) /*@Configuration*/ { ... }
public void open() /*@Configuration(after=Open.class)*/
/*@Closed(after=Open.class)*/ { ... }
public String read() /*@Open*/ { ... }
public void close() /*@Open(after=Closed.class)*/ { ... }
}
Finally, here is some example code which demonstrates what errors are caught by the typestate checker:
void readMore(@Open RemoteResourceReader rrr) { ... }
void test() {
// initially in the 'configuration' state
RemoteResourceReader rrr = new RemoteResourceReader();
// ok: correct state
rrr.setUrl("http://something");
// error: not in the 'open' state
rrr.close();
// changing state from 'configuration' to 'open'
rrr.open();
// ok
String read = rrr.read();
// error: not in the 'configuration' state
rrr.setUrl("http://different");
// ok: parameter in the 'open' state
readMore(rrr);
// ok
rrr.close();
// error: parameter not in the correct state
readMore(rrr);
}
If you’d like to make experiments with the typestate checker on your own, go ahead and download it. The setup is really easy. And remember, that your feedback is very valuable and important!
I’d like to thank Michael Ernst and the rest of the JSR308 team for helping me with some questions that I had during development. The specification and framework is really good and worth taking a look at :)
Adam
Post to del.icio.us