A More Complex Example: Serializable Classes Missing serialVersionUID

When you need to, you can combine simple search elements in a variety of ways with BBQ. We'll examine how one particular search is constructed from simpler elements in some detail. Although it might seem daunting at first, the hope is that with familiarity constructing similar queries will become almost effortless, second-nature. Eventually you may come to see more and more development tasks in terms of BBQ queries.

If you have a class that implements java.io.Serializable, it's a good idea to to have the class include a version identifier in the form of a static long field named serialVersionUID. This query will identify such classes.

First, let's find the classes that implement java.io.Serializable. Start with the class set expression, and apply the recursive derived classes of transform.

recursive derived classes of class "java.io.Serializable"

Now, we'll refine the query to include only those classes that do not have the version marker. "Does not have" in BBQ generally translates to the exists filter modified by the not operator; exists takes a transform argument that should produce whatever we are testing the existence of. In this case we are testing for a field with a certain name; we'll specify the name with the matching filter. So the transform that finds the appropriate field in the class is:

matching "serialVersionUID" fields in ...

We use that transform with the exists filter to get the more specific set expression:

not exists ( matching "serialVersionUID" fields in ) recursive derived classes of class "java.io.Serializable"

Straightforward enough, I hope, and in fact the Eclipse IDE duplicates this functionality and by default will flag such classes in your project.

The problem with the output of the query as written is that it might return a number of classes that are serializable only incidentally; for these classes you don't care if there is a serialVersionUID field. For example (making some quick use to the count expression) the Eclipse 3.1 code base has 368 Serializable classes; only 169 of these have a serialVersionUID field. Presumably, for the remaining 199 classes, it's not that important. One of the advantages of BBQ is that it lets you focus quickly on what you do think is important. Suppose you were not interested in all classes that implement Serializable, but only those that are derived from Persistent. You can readily modify the query and get exactly the list of classes that you want:

not exists ( matching "serialVersionUID" fields in ) recursive derived classes of class "Persistent"

Alternatively, you might be interested in any Serializable class within a certain package tree. You can do that by applying the transform that looks for the missing field

not exists ( matching "serialVersionUID" fields in ) ...

to the intersection of the two sets of classes: classes derived from java.io.Serializable and classes within a package tree.

recursive derived classes of class "java.io.Serializable" intersection classes in recursive ( packages in ) package "com.antlersoft"

When we construct the full expression we have to use parentheses to group the set expression because the intersection operator has low precedence:

not exists ( matching "serialVersionUID" fields in ) ( ( recursive derived classes of class "java.io.Serializable" ) intersection classes in recursive ( packages in ) package "com.antlersoft" )

When we deal with longer examples, it can help to use line breaks and indenting to see the structure of the query. A good rule is to break and indent at parentheses, and break lines before and after and back indent set operators.

	    	not exists (
	    		matching "serialVersionUID" fields in
	    	)
	    	(
	    		(
	    			recursive derived classes of class "java.io.Serializable"
	    		)
	    	  intersection
	    		classes in recursive (
	    			packages in
	    		)
	    		package "com.antlersoft"
	    	)
	    	
browse-by-query home antlersoft free software sourceforge project page