Blog of Adam Warski
Java and JBoss related stuff-
JSF2 navigation: post->redirect->get
Posted on March 11th, 2010 No commentsJSF2 improves a lot both how navigation can be done (you can now return a view id from an action method, no need to describe every navigation case in faces-config.xml) and how URLs are handled (finally, GET support). JSF2 introduces view parameters (for those who know Seam: standardized page parameters). Each page can define a metadata section, where the view parameters are described, bound to bean values, converted and validated.
As an example, a blog-entry-viewing page would define the id of the entry to be displayed as follows:
<f:metadata> <f:viewParam name="entry_id" value="#{blog.entry}" required="true"> <f:converter converterId="blog-entry-converter" /> </f:viewParam> </f:metadata>Unfortunately I had some trouble with one thing: how to redirect to a page, including the view parameters, after a POST? This post->redirect->get pattern is very common. E.g. when you post a new comment for a blog entry and press submit, the data is persisted and you want to be redirected back to
view.jsf?entry_id=819(using the default JSF command-button behavior, you would land on a plain, non-bookmarkableview.jsf).Dan Allen wrote a series of very good introductory articles to JSF2 on DZone. There, he writes that what I described above should be possible to achieve by adding a
<redirect include-view-params="true"/>tag to the appropriate<navigation-case>infaces-config.xml. Unfortunately, the xsd doesn’t allow such an attribute and it doesn’t work - I suppose that this construct didn’t make it into the final version of the spec (although somebody may correct me if I’m wrong).Another solution, this time working, can be found on Ed Burns’s blog. The trick is to return a string containing the view id and some additional parameters from the action method or use them as the command button/link action, e.g.:
public String action() { // business logic ... return "view.xhtml?faces-redirect=true&includeViewParams=true" }However this way you’ll have to repeat the combination of the “magical parameters” a lot in your code. And it’s pretty easy to do a spelling mistake in one of the strings you return. Furthermore, it’s not possible to easily include one view parameter, without repeating the value mapping.
The way I solved this is by introducing a
Navcomponent (I’m using Weld), which holds information about pages. It contains a nestedPageclass, which has a “fluent” interface for building a link. Navigation then looks as follows:@Inject private Nav nav; public String action() { // business logic ... return nav.getViewEntry().redirect().includeViewParams().s(); }Or, if you want to include only one parameter:
public String action() { // business logic ... return nav.getViewEntry().redirect().includeViewParam("name").s(); }In xhtml pages, you can also use the
navcomponent to generate links:<h:link outcome="#{nav.manageIndex.s}">Manage</h:link>Notice that you completely abstract away from the actual names of the xhtml views (pages) - they are stored centrally only in the
navcomponent! This makes any refactorings really easy.Speaking of the
navcomponent, here’s the code:/** * @author Adam Warski (adam at warski dot org) */ @Named @ApplicationScoped public class Nav { public static class Page { private final String viewId; private final Map<String, String> params; private Page(String viewId) { this.viewId = viewId; this.params = new LinkedHashMap<String, String>(); } private Page(String viewId, Map<String, String> params) { this.viewId = viewId; this.params = params; } public Page redirect() { return includeParam("faces-redirect", "true"); } public Page includeViewParams() { return includeParam("includeViewParams", "true"); } public Page includeViewParam(String name) { // Getting the metadata facet of the view FacesContext ctx = FacesContext.getCurrentInstance(); ViewDeclarationLanguage vdl = ctx.getApplication().getViewHandler() .getViewDeclarationLanguage(ctx, viewId); ViewMetadata viewMetadata = vdl.getViewMetadata(ctx, viewId); UIViewRoot viewRoot = viewMetadata.createMetadataView(ctx); UIComponent metadataFacet = viewRoot.getFacet( UIViewRoot.METADATA_FACET_NAME); // Looking for a view parameter with the specified name UIViewParameter viewParam = null; for (UIComponent child : metadataFacet.getChildren()) { if (child instanceof UIViewParameter) { UIViewParameter tempViewParam = (UIViewParameter) child; if (name.equals(tempViewParam.getName())) { viewParam = tempViewParam; break; } } } if (viewParam == null) { throw new FacesException("Unknown parameter: '" + name + "' for view: " + viewId); } // Getting the value String value = viewParam.getStringValue(ctx); return includeParam(name, value); } public Page includeParam(String name, String value) { Map<String, String> newParams = new LinkedHashMap<String, String>(params); newParams.put(name, value); return new Page(viewId, newParams); } public String s() { StringBuilder sb = new StringBuilder(); sb.append(viewId); String paramSeparator = "?"; for (Map.Entry<String, String> nameValue : params.entrySet()) { sb.append(paramSeparator).append(nameValue.getKey()) .append("=").append(nameValue.getValue()); paramSeparator = "&amp;"; } return sb.toString(); } public String getS() { return s(); } } private final Page manageIndex = new Page("/manage/index.xhtml"); private final Page manageUsers = new Page("/manage/users.xhtml"); private final Page home = new Page("/home.xhtml"); private final Page thisPage = new Page(""); // other pages ... public Page getManageIndex() { return manageIndex; } // other getters ... }Looking forward, the
Pageclass may also include e.g. security management, however that would require some more JSF bindings.Adam
-
Projects Using Envers wikipage
Posted on February 1st, 2010 No commentsI just created a new “Projects Using Envers” wikipage; so if you are using Envers in your project, make sure to add it to the list! :) If you are not yet using Envers, don’t forget to check it out when you have to implement data auditing/versioning next time.
Also, my company, SoftwareMill, is providing Envers support and services. If you are interested in a feature being added or a bug fixed, don’t hesitate to contact us!
Adam
-
Envers 1.2.2 released!
Posted on December 18th, 2009 2 commentsAfter quite a long break, I’m happy to announce a new release of Envers (available on the downloads page, or via Maven). This is mainly a bugfix release, but there are also new features:
- possibility to audit relations from audited to non-audited entites. This feature was actually one of the most asked for. You have to explicitly annotate such relations with
@Audited(targetAuditMode=NOT_AUDITED). Then, when reading historic versions of your entities, the relation will always point to the “current” version of the entity. This is mainly useful for dictionary-type entities, which never change. - new configuration properties:
org.hibernate.envers.default_schemaandorg.hibernate.envers.default_catalogwith which you can specify the default catalog/schema for audit tables - by default, when you delete an entity, in the audit table only a “marker” entry will be written with all fields
nullexcept the id. But if you want, you can now store all data of the entity by specifying theorg.hibernate.envers.store_data_at_deleteproperty to true. This is normally not needed as the data is already stored in the last revision before the delete. - experimental support for “fake” bidirectional relations, mapped with
@OneToMany+@JoinColumnon one side, and@ManyToOne+@Column(insertable=false, updatable=false)on the many side. Envers can now audit such relations without a middle table, but the user has to add an@AuditMappedByannotation. See the documentation for more details.
Also, all configuration properties were renamed from camel-case to the Hibernate standard, separating words using underscores. But don’t worry, old properties will work also. Moreover, the legacy
@Versionedannotations support was removed. If somebody didn’t yet migrate, the transition should be trivial.This release is fully compatible with Hibernate 3.3, but remember that Envers is now a Hibernate core module, so it will be also included in the coming Hibernate 3.5 release.
For a full list of resolved issues, see the Hibernate JIRA page.
Thanks to Tomasz Bech, Nicolas Rouge and Eugene Goroschenya for providing patches and all other contributors and users for valuable input on the forums and in JIRA! As always, feedback is very welcome.
Envers also has a new homepage; big thanks for the work to Rysiek, Joseph and the JBoss.ORG team!
Merry Christmas!
Adam - possibility to audit relations from audited to non-audited entites. This feature was actually one of the most asked for. You have to explicitly annotate such relations with
-
Dependency Injection and replacing dependencies in CDI/Weld
Posted on December 16th, 2009 No commentsFrom time to time, in a system I develop, which uses EJB3 beans as the basic “component model”, I have a need to do some operations using a new entity manager (but still in the same transaction). The problem here is that if I invoke a method on another bean, which has an entity manager injected (using
@PersistenceContext EntityManager em), the entity manager will be the original one. There is no way to temporarily replace it or any other dependency, just for the time of one invocation.That’s why I wanted to see if that would be possible to achieve using the recently released Weld framework, reference implementation of the CDI specification (part of JEE 6). Unlike in Seam, where injection is done whenever a method on a managed bean is invoked (which would theoretically make it easier to do the temporary replacement), in CDI injection happens once, when the objects are constructed. So the only way (at least the only way I see) to implement temporary replacement is to wrap the injected beans in some kind of an interceptor.
In CDI, injected beans can either be “stand-alone”, or come from a producer (factory) method (annotated with
@Producer). AsEntityManagers are typically created by producer methods, in the example below I assume this scenario. It is possible to slightly change the code so that it works for normal beans, however I didn’t manage to create a nice universal solution (which wouldn’t simply do an “if” to check if the bean is created by a producer method).To test, we define a simple bean which will have a dependency injected via constructor injection:
@ApplicationScoped public class FirstBean implements Serializable { private ISecondBean second; public FirstBean() { } @Inject public FirstBean(ISecondBean second) { this.second = second; } public void start(int c) { System.out.println("Type of second: " + second.getMessage(c)); } }The interface
ISecondBeanhas two implementations:public interface ISecondBean extends Serializable { String getMessage(int c); } @Alternative public class SecondBeanA implements ISecondBean { public String getMessage(int c) { return "variant A; " + c; } } @Alternative public class SecondBeanB implements ISecondBean { public String getMessage(int c) { return "variant B; " + c; } }The
@Alternativeannotation makes the bean disabled by default, so that Weld doesn’t try to inject an instance of it when there’s a matching injection point. That’s because we want to produce implementations ofISecondBeanusing a producer method:@ApplicationScoped public class SecondBeanProducer { @Produces public ISecondBean getSecondBean() { return new SecondBeanA(); // by default we use the A variant } }A very nice feature of Weld/CDI, especially for evaluation purposes, is that it’s possible to use it very easily in Java SE. To test our beans, all we need to do is run the
org.jboss.weld.environment.se.StartMain, putting a jar with our classes in the classpath. One important thing is that the jar must contain abeans.xmlfile (it can be empty, but it must exist). We can observe the container startup-event to do some work:@ApplicationScoped public class Main { @Inject private FirstBean first; public void start(@Observes ContainerInitialized event) throws Exception { System.out.println("Welcome to Main!"); first.start(1); first.start(2); first.start(3); } }The result will be:
Welcome to Main! Type of second: variant A; 1 Type of second: variant A; 2 Type of second: variant A; 3
Now we finally come to the point of implementing the replaceable dependencies. As you may have guessed,
ISecondBeancorresponds toEntityManager, and that’s the dependency that we will try to replace.To do that, we first have to define an interceptor. That’s quite easy and intuitive in CDI/Weld (documentation here). There are three steps:
- write an annotation, which will be an interceptor binding: all methods annotated with that annotation will be intercepted
- write the interceptor, annotating it with the annotation created earlier: that way Weld will know that the annotation binds the given interceptor
- enable the interceptor in beans.xml
Here’s the code (full interceptor code below):
@InterceptorBinding @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) public @interface ReplaceableResult { } @Interceptor @ReplaceableResult public class ReplaceableResultInterceptor { @AroundInvoke public Object replace(InvocationContext ctx) throws Exception { ... } }<beans> <interceptors> <class>test.ReplaceableResultInterceptor</class> </interceptors> </beans>Adding an interceptor for a method is easy: if we want to be able to temporarily replace implementations of
ISecondBean, all we need to do is annotate the producer method with the new annotation.SecondBeanProducernow takes the form:@ApplicationScoped public class SecondBeanProducer { @Produces @ReplaceableResult public ISecondBean getSecondBean() { return new SecondBeanA(); // by default we use the A variant } }We can now test the temporary replacement by modifying the
Mainbean that we used before:@ApplicationScoped public class Main { @Inject private FirstBean first; public void start(@Observes ContainerInitialized event) throws Exception { System.out.println("Welcome to Main!"); first.start(1); // Here we replace the implementation of ISecondBean just for // the duration of one method call. ReplaceableResultInterceptor.withReplacement( ISecondBean.class, new SecondBeanB(), // we are using the B variant new Callable<Void>() { @Override public Void call() throws Exception { first.start(2); return null; } }); first.start(3); } }The result will now be:
Welcome to Main! Type of second: variant A; 1 Type of second: variant B; 2 Type of second: variant A; 3
So the dependency in
FirstBeanwas swapped! Which was our goal: for the duration of the bean method invocation, whenever aISecondBeandependency is injected, the temporary implementation will be used.
Full code of the interceptor:@Interceptor @ReplaceableResult public class ReplaceableResultInterceptor { private static ThreadLocal<Map<Class<?>, Object>> replacements = new ThreadLocal<Map<Class<?>, Object>>() { @Override protected Map<Class<?>, Object> initialValue() { return new HashMap<Class<?>, Object>(); } }; @AroundInvoke public Object replace(InvocationContext ctx) throws Exception { Class<?> returnType = ctx.getMethod().getReturnType(); if (!returnType.isInterface()) { throw new UnsupportedOperationException("Only results of methods " + "which produce implementations of an interface can be replaced!"); } // Getting the result of the producer method Object result = ctx.proceed(); // Wrapping it in an interceptor, which on an invocation will check if // there's a replacement result = Proxy.newProxyInstance( returnType.getClassLoader(), new Class[] { returnType }, new ReplaceableInterceptor(returnType, result)); return result; } public static <V> V withReplacement(Class<?> replacing, Object replacement, Callable<V> toCall) throws Exception { boolean hasOld = false; Object old = null; try { hasOld = replacements.get().containsKey(replacing); old = replacements.get().put(replacing, replacement); return toCall.call(); } finally { if (hasOld) { replacements.get().put(replacing, old); } else { replacements.get().remove(replacing); } } } private class ReplaceableInterceptor implements InvocationHandler { private final Class<?> replacementsKey; private final Object delegate; private ReplaceableInterceptor(Class<?> replacementsKey, Object delegate) { this.replacementsKey = replacementsKey; this.delegate = delegate; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (replacements.get().containsKey(replacementsKey)) { return method.invoke(replacements.get().get(replacementsKey), args); } else { return method.invoke(delegate, args); } } } }Overall, CDI/Weld works very well and I’m very satisfied with it. One thing I’m missing is being to able to do programmatic configuration (Guice-style), but it’s already in the list of ideas for future portable extensions. I think that programmatic configuration and the ability to run Weld in JavaSE will create a great mix for “semi-integration” testing.
Adam
-
Nonnull-check generator: a scala compiler plugin
Posted on October 15th, 2009 No commentsRecently I played a bit with compiler plugins for Scala.
My goal is to write a plugin which would generate checks in code for methods annotated with JSR305 annotations. As a first step, I wanted to handle the
@Nonnullannotation on parameters. Supposing you have the following code:def parameterMustBeNull(@Nonnull parameter : Object) = { parameter.toString(); }the compiler plugin should transform it to:
def parameterMustBeNull(@Nonnull parameter : Object) = { if (param == null) throw new IllegalArgumentException("Parameter 'parameter' should not be null.") parameter.toString(); }That way, the method contract expressed by annotations in the method header doesn’t have to be duplicated by explicit checks in the code later - they are generated automatically.
To achieve that, the plugin must first find the parameters that are annotated with
@Nonnull. Then, for each such parameter, it must generate a tree corresponding to theifpart. Finally, these generated chunks of code must be added to the beginning of the body of the method. All of this is quite easy to do thanks to the Scala compiler API and the AST that you can inspect and manipulate. But I think it’s best just to look at source code.In some more detail, as we want to transform the AST, the plugin must use the
Transformtrait. Then we have to implement the transform method, which looks if the tree passed is a method and if so, looks for the nonnull parameters:object AnnotationsCheckGenComponent extends PluginComponent with Transform { ... object AnnotationsCheckGenTransformer extends Transformer { override def transform(tree: Tree) = { tree match { // DefDef is a method definition case dd @ DefDef(_, _, _, vparamss, _, _) => { // here we add the nonnull checks } case t => super.transform(t) } }The
vparamsslist holds the list of parameters. To search for parameters which are annotated with a nonnull annotation, we can use the very handy Scala list manipulation methods:vparamss.flatten[ValDef].filter(param => { // Checking if the parameter contains a non-null annotation param.mods.annotations.exists(annotation => { // Checking if the annotation is a non-null annotation annotation.constr.find(tree => { tree match { case Ident(name) => "No[nt][Nn]ull".r.findFirstIn(name.toString).isDefined case _ => false } }).isDefined }) })As you can see above, any nonnull annotation will be detected, not only the ones defined by JSR305. And finally, for each parameter annotated, we must generate the if block containing the check. It’s almost like writing the code directly ;).
If( // if: param == ... Apply( Select( Ident(param.name), newTermName("$eq$eq")), List(Literal(Constant(null))) ), // then: throw ... Throw( Apply( Select( New(Ident(newTypeName("IllegalArgumentException"))), newTermName("<init>")), List(Literal(Constant("Parameter '%s' should not be null.".format(param.name)))))), // else EmptyTree)To use the plugin during compiling, all you need to do is have a jar (you can download a ready one here) that includes the compiled plugin class and a descriptor, and run the compilation with the
-Xpluginparameter, for example:scalac -cp $JSR305_JAR_PATH -Xplugin:annotations-check-gen.jar Example.scala
The only problem I had was in which phase the plugin should be executed. At first I tried executing it after
namer, and later, taking the advice I got on the forums (by the way, the forum members are really helpful), aftertyper. However, then I had to run the typer again on the generated code, and I didn’t yet figure out how to type the generatedifin a context of the method, so that the typer has access to the information about available values (here, the value being the parameter checked is used). So for now, instead, the plugin runs after theparserphase (so in fact as the first plugin), and then the result handled by the rest of the phases as if the code was there from the beginning. But if somebody has an idea, on how to run the typer properly, please let me know :).You can find the entire source code on github. For building and testing I used buildr. I must say that writing the build using that tool was a lot more pleasant than using Maven2, even considering the fact that I don’t know Ruby.
The plugin can be extended to generate checks for other annotations, for example
@MatchesPattern,@RegExetc. Another thing to do is to generate checks also for return values of methods (e.g. if a method is annotated with@Nonnull, this means that the return value shuoldn’t benull). This is a bit more tricky however, as there can be many exit points from the method. Going further, the generation can be extended to more advanced method contracts, expressed for example via typestate annotations.If you are also interested in writing compiler plugins for Scala you can find a good tutorial here, and a step-by-step guide describing another plugin here.
Adam
-
Typestate checker - checking iterators
Posted on September 23rd, 2009 No commentsIn the new 0.2.2 release of the typestate checker (an extension to the JSR308 checkers framework), you can now specify a state, to which an object transits, if a method returns true or false using the afterTrue and afterFalse elements in state annotations.
A good use-case and example is an Iterator. As you probably know, before calling next(), it’s good to check if an element is available using hasNext(). So we can distinguish two “states” of an iterator: CheckHasNext - which means that it is unknown if an element is available or not and ReadNext, in which it is safe to call next().
After calling hasNext(), the iterator should transit to the ReadNext state, but only if the method returns true. Also, after calling next(), the iterator should always transit to the CheckHasNext state. Using typestate annotations, we can write that specification on a stub of the Iterator interface:
public interface Iterator<E> { public abstract boolean hasNext() @CheckHasNext(afterTrue=ReadNext.class) @ReadNext; public abstract E next() @ReadNext(after=CheckHasNext.class); public abstract void remove(); }Here I am using annotations on the receiver of the method, a new place where you can put annotations introduced with JSR308.
You can download the definitions of the stubs and the states in an easy-to-run example here. All you need to do is edit the example.sh file to specify the path to the JSR308 distribution, which you can download from its homepage. There are several example source code files which you can typestate-check. It is also quite easy to typestate check your own files - just change the SOURCES parameter of javac.
For example, this snippet of code checks without errors:
Iterator iter = collection.iterator(); while (iter.hasNext()) { iter.next(); }While this throws an error on line 5:
Iterator iter = collection.iterator(); while (iter.hasNext()) { iter.next(); } iter.next(); // error: iter is in a wrong stateYou can find the newest release available for download on the checker’s homepage, as well as in a maven2 repository. The source code is available on github.
Have fun!
Adam -
Javarsovia, static analysis and annotations
Posted on July 2nd, 2009 No commentsIf 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 -
Envers on Jazoon
Posted on June 21st, 2009 No commentsIf 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 -
Envers 1.2.1.GA released
Posted on June 6th, 2009 6 commentsYesterday 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 theAuditReader.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 -
StaticAccess detector for FindBugs
Posted on May 11th, 2009 2 commentsThe 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

