Java Champion / JavaOne Rockstar Adam Bien (adam-bien.com) is a self-employed consultant, lecturer, software architect, developer, and author in the enterprise Java sector. He is also the author of several books and articles on Java and Java EE technology, as well as distributed Java programming. adam has posted 59 posts at DZone. View Full User Profile

Silent Death Of The Classic Marker Interface Pattern: Is java.io.Serializable Legacy?

09.02.2008
| 7211 views |
  • submit to reddit
I was in the process of thinking about @Stateless and JPA and Serializable (needed some examples for my book...) and noticed that actually one of the GoF patterns siltently died. Or at least its realization/implementation has been completely refactored. The Marker Interface pattern was used to enhance a class with an additional type to change its behavior or introduce some priviliged actions. Prominent examples are java.io.Serializable and java.rmi.Remote interfaces. Both were introduced because of security reasons. Only classes which implement those interfaces are able to be flushed to disc or transfered over the network.

With the advent of annotations, the approach whereby you implement an interface is actually no longer appropriate. The usage of annotations @Serializable or @Remote is much more elegant. There is an example of this in JSR-181, where an endpoint has only to be annotated with the @WebServce annotation. No additional interface realization/implementation is necessary.

Using an annotation is not the same as implementing an interface, because the type of the class is not going to be extended. Nonetheless, the same effect can be achieved. So, the infrastructure no longer needs to check the type (e.g., with instanceof), but has to check the existence of the annotation via reflection (class#getAnnotation or isAnnotationPresent) instead.

So java.io.Serializable and java.rmi.Remote are actually legacy now!

From http://www.adam-bien.com/roller/abien/

AttachmentSize
fig-1.png2.85 KB
Published at DZone with permission of its author, adam bien.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Serge Bureau replied on Tue, 2008/09/02 - 7:50am

Good Morning,

 

it is in fact unfortunate, as I find annotations a code nuisance at best.

It totally looks foreign to Java, plus most annotations are tools related and not applicable for most users.

Annotations is code pollution, readability seems to not be a concern anymore.

 

So I am sorry but I prefer the marker pattern a lot. 

adam bien replied on Tue, 2008/09/02 - 8:10am in response to: Serge Bureau

[quote=SergeBureau]Annotations is code pollution, readability seems to not be a concern anymore.

 So I am sorry but I prefer the marker pattern a lot. 

[/quote]

 

So, you don't like the annotations in general and therefore you prefer MarkerInterface?

John Denver replied on Tue, 2008/09/02 - 11:41am

The problem of this kind of questions it ends in flame wars because everybody have diferent point of view so for some folks is more elegant the marker pattern for others the annotation.

I think the best is like Spring 2.5 that bring both worlds you can configure with annotations your bean or continue the traditional way with xml.

Me personaly I like annotations it makes less verbose Java but yes it brings foreign syntax to the code.

Regards.

 

Casper Bang replied on Tue, 2008/09/02 - 11:59am

I pollitely beg to disagree a little. A marker interface becomes part of the signature, so you retain a lot of type safety in your design. I can't even begin to tell you how frustrating it is to only have your program validated when you have compiled, deployed and run the application (JPA queries, JSR-296 Actions etc.), so I'm with Serge on this one.

But in general, the whole meta-data space in Java is messed up. We use a "transient" modifier on a variable to signify it should not be serialized, that's a kind of annotation. We use @deprecated inside JavaDoc, that's another kind of annotation IDE's and compilers pick up on. Of course it has now been replaced by SuppressWarnings("deprecation") which again was replaced by @Deprecated. We also got a SuppressWarnings("overrides") to use, which now seems to have been replaced by @Override

That's what scares me the most about annotations, how they allow all kind of type-unsafe crap to be stuffed into them.

Danail Nachev replied on Tue, 2008/09/02 - 11:57am

So, if it is in the language spec it will be included in the IDE, if not, it is unknown. The only gain to having additional keyword in the language is to make sure that your IDE will parse it and validate it. I don't think this is necessary. Annotations are type-safe enough to be handled by an IDE and there is no need for any additions in the language.

Casper Bang replied on Tue, 2008/09/02 - 12:08pm in response to: Danail Nachev

"So, if it is in the language spec it will be included in the IDE, if not, it is unknown."

Have you tried using SuppressWarnings across compilers and IDE's? It's a confusing and unreliable endeavour because the JLS only mandates "unchecked".

"The only gain to having additional keyword in the language is to make sure that your IDE will parse it and validate it."

Not true. If @Override had been introduced as a keyword, it would've allowed safer API evolution in the sence that if a new method is introduced to a base class that just so happens to clash with one you added to the superclass, it won't blow up on you.

Raveman Ravemanus replied on Tue, 2008/09/02 - 12:16pm

I saw worst examples, from SpringMVC 2.5

 

@Controller
@RequestMapping("/home.htm")
public class HomePageController {
@RequestMapping(method = RequestMethod.GET)
public String showHomePage(ModelMap model) {
model.addAttribute(rantService.getRecentRants());

return "home";
}

@Autowired
RantService rantService;
}
 link: http://www.jroller.com/habuma/entry/unit_testing_spring_mvc_it
 
 
I dont mind any annotation except weird method showHomePage, what if I change it to
   public String showHomePage(Map model) {
will it work? it will compile. You have to copy and paste that code, because compiler wont help you here. Would implementing interface here hurt so much?
Would adding methods like abstract String RequestMapping(); to that interface hurt also? Why not use Ruby? Its more dynamic and i think its better that this.
Plus i think every annotation here is optional, will it work if i dont declare some annotation and declare it in XML? i dont know.
Sun must be mad that they cant use it in their SCWCD test, i bet. But i heard they try to make Servlets weird, so good for them.

John Denver replied on Tue, 2008/09/02 - 12:19pm

This is just my opinion and is a rant to Java if you dont want to read it just don't read this comment.

Already talking about annotations and the marker pattern, this is when I come to some conclusions. I like Java is my language of choice and I like annotations but I think Java need the annotations to keep forward, Java code is to verbose and now is getting popular the dynamic typing and scripting languages.

But I think like Bruce Tate, Java already got until the end of the road and getting new features and bloating the language is not the solution, Java was never meant for dynamic features, closures and bunch more even annotations all those are just bloating and getting complicate the Java language.

The solution to this is out there, but nobody knows where, some say is Ruby or Python or Groovy anothers say is Scala or Erlang and anothers say a new complete language.

Now, we are on the Grid/Cloud/Services/Web era and for that I think in my opinion is that Erlang is a good candidate, It is an easy language to learn with all the features everybody wants, dynamic, functional, concurrent, message passing and no shared mem, the vm is mature with many features and it is exatly for what we are heading right now Grid/Cloud/Services/Web/Multicore/Network and already is in production for many years, so we dont need to bloat Java a make it more complicate, it is just pick Erlang and have all the features everybody wants right now and it is easy plus Erlang works very good with Flex let me tell you so you have the best of the best.

Note: (Of course this is for new projects and beyond,  Im not talking about to port a Java legacy system to Erlang right now, that could be stupid).

this is my 2c.

Regards.

Alex(JAlexoid) ... replied on Tue, 2008/09/02 - 3:52pm

[quote=Casper Bang]We use @deprecated inside JavaDoc, that's another kind of annotation IDE's and compilers pick up on. Of course it has now been replaced by SuppressWarnings("deprecation") which again was replaced by @Deprecated. We also got a SuppressWarnings("overrides") to use, which now seems to have been replaced by @Override[/quote]

Sorry to be Slashdotty here, but your statement is in need of serious correction. Since by the looks of it you dont even uderstand the difference between annotation @SuppressWarnings("deprecation"), JavaDoc @deprecated and annotation @Deprecated.
@SuppressWarnings("deprecation") will spuress the deprecated API usage warnings by compiler.
JavaDoc @deprecated marks something deprecated and annotation @Deprecated will do the same.
Same goes for @Override and SuppressWarnings("overrides")

[quote=Sidewinder]Java was never meant for dynamic features, closures and bunch more even annotations all those are just bloating and getting complicate the Java language.[/quote]

Java is dynamic enough for frameworks like Spring to exist. Be it totally static, we would probably not have the class metadata accessible. So closures seem to be less dynamic then reflection API and dynamic proxy API.

Casper Bang replied on Tue, 2008/09/02 - 6:03pm

Yeah sorry I got that mixed up a bit, @Deprecated is obviously for exporting while @SuppressWarnings("deprecation") is for consuming. My original point still stands though, throughout the API's there are several different ways of assigning meta-data depending on what we're talking about. And it feels somewhat random what is implemented as marker interface (Serializable) vs. JavaDoc token (@deprecated) vs. keyword (transient) vs. annotation (@Override).

Howard Lovatt replied on Tue, 2008/09/02 - 7:16pm

It would be nice to get rid of marker interfaces but at the moment this isn't possible. If you make an interface e.g. java.security.Key that implements Serializable then any class that implements Key is automatically Serializable. Unfortunately you can't get a class to inherite an annotation from an interface, I think this limitation is to be addressed in a JSR.

Danail Nachev replied on Wed, 2008/09/03 - 3:09am

@raveman: Unappropriate usage of Annotations instead of interfaces is another thing. But annotations can easily replace marker interfaces. Because they do nothing more than being marker:) The only valid thing may be is that you cannot force your successors to add the annotation, although the annotation processing might traverse the whole hierarchy, if this is the required behaviour.

 

@Casper Bang: I have to admit that I have never used annotations:) However, I still cannot grasp the difference between using keyword and using annotations. Depending on the compiler/IDE logic, they should be the same. If they aren't, the problem is not in the idea of annotations, but how they are used.

Tib Onu replied on Wed, 2008/09/03 - 4:22pm

"The usage of annotations @Serializable or @Remote is much more elegant"

That might be true (it's a matter of taste) but using annotations as markers raises type safety issues (most notably one cannot properly specify the marker type in a method signature).

Also, just to be more accurate, "Marker Interface" is not a GoF pattern.

erwin de ley replied on Thu, 2008/09/04 - 10:16am in response to: Casper Bang

I agree with Casper's 1st reply. Especially the type-safety is an important difference, which by itself makes a marker interface much more usefull than an annotation in lots of cases.

 

E.g. in an API definition for some weird communication service, Serializable could come in handy as in :

public interface MessageSender {

void sendMessage(Destination d, Serializable msg) throws WhateverKindOfException;

}

 

If we would need to make a signature with plain Object, and then check for presence of an annotation etc, we only can check the correctness of the program at runtime (as Casper clearly mentions).

 

I'm not a fan of annotations, but I see their value for meta-data stuff, e.g. as field decorators etc. But for class markers, marker interfaces are the thing!

Annotations don't offer any advantage in that space, as far as I can tell...

 

 

 

 

Danail Nachev replied on Thu, 2008/09/04 - 11:10am in response to: erwin de ley

I cannot argue with you:)

Serge Bureau replied on Thu, 2008/09/04 - 11:42am in response to: adam bien

So, you don't like the annotations in general and therefore you prefer MarkerInterface?

 

Absolutely. I think annotation is a mistake. Tags are unclear and change from tool to tool, it is an Anti-Pattern 

Casper Bang replied on Thu, 2008/09/04 - 12:08pm in response to: Serge Bureau

But it did probably extend the lifetime of Java, or I should say, it allows SUN to go even longer without touching their holy grail of backwards compatibility. So we can wonder about what's coming next, a preprocessor? ;)

Serge Bureau replied on Thu, 2008/09/04 - 1:32pm in response to: Danail Nachev

I am sorry to disagree,

the problem is not in the idea of annotations, but how they are used.

I do think that Annotations is an aberration, it is not needed.

Not needed would not be too bad, but nothing can stop the proliferation of flags and it makes code vey difficult to read.

So please deprecate them !!! 

Serge Bureau replied on Thu, 2008/09/04 - 1:37pm in response to: Casper Bang

Sorry but I do not see how ? But it did probably extend the lifetime of Java

It has no real utility. They should think about incorporating Groovy and really then improve Java.

Annotations and autoboxing/unboxing are a dangerous step back !! 

Tib Onu replied on Thu, 2008/09/04 - 1:59pm in response to: Serge Bureau

"Annotations and autoboxing/unboxing are a dangerous step back !!"

Why? Why is autoboxing (or annotations for that matter) a dangerous step back and why would "incorporating Groovy" into Java (whatever that means) be an improvement?

If you want to do Java-like dynamic programming, use Groovy.

Serge Bureau replied on Fri, 2008/09/05 - 7:57am in response to: Tib Onu

[quote=tib_onu]

"Annotations and autoboxing/unboxing are a dangerous step back !!"

Why? Why is autoboxing (or annotations for that matter) a dangerous step back and why would "incorporating Groovy" into Java (whatever that means) be an improvement?

If you want to do Java-like dynamic programming, use Groovy.

[/quote]

My point is thta having dynamic capabilities plus closures is quite an improvement, not to mention it brings AOP capabilities.

Loosing tiime on autoboxing and annotations was/is a mistake.

Autoboxing brings us back to C that converts freely anything without complaining, plus it makes code less readable. What worst consequences do you need ??

Annotations on the other end is not needed, plus it is mainly designed for tools and it stays there even for those not using the referred tool, so when you get code from open source projects you will inhirit all kind of "garbage". So we should have the garbage collector taking care of Annotations ;-) 

Tib Onu replied on Fri, 2008/09/05 - 8:38pm in response to: Serge Bureau

Wow, I don't even know where to begin here ... You're obviously confusing stuff left and right.

First of all, "dynamic capabilities" + closures have nothing to do with AOP. AOP can be implemented in any kind of language (procedural, OO or functional), there are many AOP implementations for Java and last time I checked, Java was still a strongly typed language (with no closures or "dynamic capabilities").

 "Loosing tiime on autoboxing and annotations was/is a mistake." - who lost time on autoboxing and annotations and how much time did he/she loose? How do we quantify this?

" Autoboxing brings us back to C that converts freely anything without complaining" - OMG, can you give an example? I did my fair share of C/C++ coding but never run into C freely converting anything without complaining. And BTW - which is more readable:

map.put("key", 123);

or:

map .put("key", new Integer(123)); 

?

Finally, regarding the annotations - they were introduced in order to provide a way of adding syntactic metadata. Prior to their introduction the same was accomplished by using all kind of XML descriptors. (Taking about "garbage" ...).

Here, let me give you one more example - and let's take a simple JUnit test as an example. Which one is better:

public class SomeTestCase extends TestCase
{
public void testOne()
{
// Some test
}
}

 or:

 

public class SomeTestCase
{
@Test public void testOne()
{
// Some test
}
}
? 

 

The first has Junit dependencies (extends TestCase), the second one has none.

 

 

 

Milind Rao replied on Mon, 2008/09/08 - 9:55am in response to: Casper Bang

Depends. I *love* @Override. It's saved my hide on numerous occasions while refactoring.
Class A
{
   void foo(int x) {}
}

Class B extends A
{
   @Override
   void foo(int x) {}
}
If I change the method signature of foo in A from int to long, I immediately get a compile error in B if I have the annotation. If I don't, I have a subtle bug since B's foo now turns from an overridden method to an overloaded method. Depending on how complex your code is, this may be difficult to track down.

Serge Bureau replied on Tue, 2008/09/09 - 1:25pm in response to: Tib Onu

[quote=tib_onu]

Wow, I don't even know where to begin here ... You're obviously confusing stuff left and right.

First of all, "dynamic capabilities" + closures have nothing to do with AOP. AOP can be implemented in any kind of language (procedural, OO or functional), there are many AOP implementations for Java and last time I checked, Java was still a strongly typed language (with no closures or "dynamic capabilities").

"Loosing tiime on autoboxing and annotations was/is a mistake." - who lost time on autoboxing and annotations and how much time did he/she loose? How do we quantify this?

" Autoboxing brings us back to C that converts freely anything without complaining" - OMG, can you give an example? I did my fair share of C/C++ coding but never run into C freely converting anything without complaining. And BTW - which is more readable:

map.put("key", 123);

or:

map .put("key", new Integer(123)); 

?

Finally, regarding the annotations - they were introduced in order to provide a way of adding syntactic metadata. Prior to their introduction the same was accomplished by using all kind of XML descriptors. (Taking about "garbage" ...).

Here, let me give you one more example - and let's take a simple JUnit test as an example. Which one is better:

public class SomeTestCase extends TestCase
{
public void testOne()
{
// Some test
}
}

or:

 

public class SomeTestCase
{
@Test public void testOne()
{
// Some test
}
}
? 

 

The first has Junit dependencies (extends TestCase), the second one has none.

 [/quote]

 

Sorry but there is no confusion .

Go back and see how the dynamic capabilities of Groovy allows capture and modification on calls with possibility of acting before, after or during a call. This is exactly AOP. But it is a very small part of what Groovy brings.

Java does not have closures, you are right. Groovy however brings it.

Your autoboxing example proves my point , in the autoboxing side what is saying that I want an integer a float or a double ? Autoboxing is imprecise, so it is not to be used.

As far as annotations it is like XML tagging, it spreads all over the place and the meaning is not at all explicit, once again highly not recommanded.

Tib Onu replied on Wed, 2008/09/10 - 9:14am in response to: Serge Bureau

Funny.

Advocating the dynamic capabilities in Groovy while stating that "autoboxing is imprecise, so it is not to be used". Let's see, so this is OK:

def int x = 0;
def double y = 5.5;
x = y;
println(x);
 

but:

map.put("key", 123);

 is not. Makes sense ... BTW, you know you can do stuff like this:

map.put("key", 123L);
map.put("key", 123.0);
map.put("key", 123.0f);
 

which allows you to control the type of the object being stored in the map.

 Going back to the AOP, while the Groovy MOP provides the language with out-of-the-box AOP capabilities, the AOP concept has nothing to do with the language being dynamic or not and you can currently do AOP in Java, C#, JavaScript, Perl, Delphi, Cobol, Flash AS - and the list goes on.


Serge Bureau replied on Thu, 2008/09/11 - 12:12pm in response to: Tib Onu

Please, the context is different as in Groovy there is no primitives so conversion of them is mandatory.

 

When did I wrote that AOP could not exist in other languages ? Please find a quote ?

 

But it is an aftertough in the languages you named, and not part of the language. In Groovy this capability is but a small part of what Groovy brings.

Alex(JAlexoid) ... replied on Thu, 2008/09/11 - 6:25pm in response to: Serge Bureau

 [quote=Serge Bureau]When did I wrote that AOP could not exist in other languages ?[/quote]

You never did say, that. But tib_onu replied to your following comment:

[quote=Serge Bureau]Go back and see how the dynamic capabilities of Groovy allows capture and modification on calls with possibility of acting before, after or during a call. This is exactly AOP. [/quote]

So I will back tib_onu here with his quote: "AOP concept has nothing to do with the language being dynamic or not"

[quote=Serge Bureau]...context is different as in Groovy there is no primitives so conversion of them is mandatory[/quote]

I don't know groovy well but in this case:

def int x = 0;  
def double y = 5.5;
x = y;
println(x);

There is an implicit conversion. This is exactly what is happening in the autoboxing case.

 

This session of flame wars is brought to you by Brawndo - The Thirst Mutilator! It's got E-LEC-TRO-LYTES.

Tib Onu replied on Sun, 2008/09/14 - 8:49am in response to: Alex(JAlexoid) Panzin

"There is an implicit conversion. This is exactly what is happening in the autoboxing case."

 Exactly, only in the Groovy case there's also some precision loss going on.  You cannot do either of the following with unboxing:

int x0 = 0;
double y0 = 0.0;
x0 = y0; // no unboxing here, but this is not allowed in Java

// Neither are the following:

int x1 = 0;
Double y1 = 0.0;
x1 = y1; // compiling error here

Integer x2 = 0;
double y2 = 0.0;
x2 = y2; // compiling error here


y2 = x2; // this is OK, no precission loss

So there's really no difference in terms of the implicit conversion handling between the primitive value operations and unboxing operations. The equivalent Groovy code snippet gets executed without even a warning and precision is lost.

Serge Bureau replied on Mon, 2008/09/15 - 1:05pm in response to: Tib Onu

Sorry to deflate your argument tib_onu,

 

but one of the precept of Groovy is to be compatible with Java, so it does for now support autoboxing/unboxing. So what is supposed to be your argument ? If Java gets rid of this stupidity then Groovy might follow. For now compatibility has it's price.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.