Java generics end of mystery

2009-04-30  |   |  java  

Remember my puzzlement in front of http://blog.emmanuelbernard.com/2009/04/java-generics-mystery.html?

I usually try to make sense of the unknown type by looking at what should be allowed when two incompatible types are used as the unknown type, and then using the generic type using the unknown type as a reference to a known type to see what incorrect things can be done through the reference. If the assignment your questioning was allowed, you would be able to add two incompatible ConstraintValidators to the validatedAddresses as in:

class Address {}
class Person {}

// A set of ConstraintValidator for Address
Set<ConstraintValidator<Address>> validatedAddresses =
    new HashSet<ConstraintValidator<Address>>();

// A set of ConstraintValidator of a single unknown type (*)
Set<ConstraintValidator<?>> validatedThings = validatedAddresses;

ConstraintValidator<Address> a;
ConstraintValidator<Person> p;

// A ConstraintValidator of unknown type, ? = Address
ConstraintValidator<?> thingA = a;

// A ConstraintValidator of unknown type, ? = Person
ConstraintValidator<?> thingP = p;

// This would be allowed if (*) was a valid assignment, which puts a ConstraintValidator<Person> in a set of ConstraintValidator<Address>

validatedThings.add(thingP);


What I missed initially is that I cannot add new (and potentially heterogeneous) elements in Set<?> or Set<? extends X>, but I am free to add elements in Set<X<?>>:


Set<A<?>> c1 = new HashSet<A<?>>();
c1.add( new A<B>() );
c1.add( new A<C>() );

Set<? extends A<?>> c1 = new HashSet<A<?>>();
c1.add( new A<B>() ); <-- compilation error
c1.add( new A<C>() ); <-- compilation error

While the first example compiles, the second does not.

So to answer my initial mystery, I need to use the <? extends X<?>> approach (thanks Vivien for pointing that out).

Set<? extends ConstraintValidator<?>> valiatedThings = ...;


Java generics mystery

2009-04-29  |   |  java  

Here is a puzzle for Generics gurus.

Can somebody explain why

Set<Address> addresses = new HashSet<Address>();
Set<?> things = addresses;

compiles but

Set<ConstraintValidator<Address>> validatedAddresses = 
    new HashSet<ConstraintValidator<Address>>();
Set<ConstraintValidator<?>> validatedThings =
    validatedAddresses;

does not compile?

More specifically, the assignment on the second line breaks.


Oracle is buying Sun: best quotes of the day

2009-04-20  |   |  java  

Alex Miller: "Next version of Java will be Java SE 7.0.0.0.17832"

Emmanuel Bernard: "The day an Oracle swallows the Sun and in front the Business Machine. No kidding it's a Titans fight."

Max Andersen: Thinking when Orsun will introduce a String in Java that says null == ""

Alexis MP: "Checking my blog posts tagged with "oracle". No need to MarcF' them ;)"

Bruno Georges: "yes, this came out of the Blue :-)"

Stomp Rasta: "There'll have Java SE 7 Lite (300 MB) and Java SE 7 Full (600 MB). And we'll have to pay for each VM installed."

Add your own...


Les Cast Codeurs Podcast is born

2009-04-14  |   |  java   jboss   podcast  

I have just started a new podcast with a few French open source activists. All about Java, all in French. If you know French, read on ; otherwise, well... learn :)

Les Cast Codeurs Podcast est dans les bacs!

Le podcast en français dans le code sur Java par Emmanuel Bernard (JBoss, Hibernate), Guillaume Laforge (SpringSource, Groovy), Antonio Goncalves (freelance, auteur), Vincent Massol (XWiki, Maven).

Restez informés sur les sujets brûlants de l'industrie Java. Plongez sur un sujet précis avec l'interview de l'épisode. Supportez les radotages de vos hôtes.

Ecoutez-nous et faites passer le message autour de vous !

web: http://lescastcodeurs.com
itunes: http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=312239675
podcast syndication: http://lescastcodeurs.com/podcast-rss
blog feed: http://lescastcodeurs.com/feed/
feedback: commentaire@lescastcodeurs.com


Podcast on Bean Validation lastest PFD

2009-04-03  |   |  java   jboss   JSR-303  

I have recently been interviewed by Kenneth Rimple for the Chariot TechCast.

In this podcast, we speak to JBoss's Emmanuel Bernard on the future of validation using JSR-303, the Bean Validation framework. JSR-303 aims to provide an annotation-driven mechanism to mark plain old java beans with annotations, such as @NotNull, @Min, @Max, and can support custom validation annotations as well.

JSR-303 is part of the Java EE 6 suite of JSRs and will be used automatically out of the box by frameworks such as JSF 2.0. Emmanuel also goes into some detail about the current state of Hibernate Search.

You can listen to it here or register to iTunes.


DevNexus: human friendly conference March 10-11 in Atlanta

2009-01-24  |   |  conference   java   jboss  

I will be speaking at DevNexus. This small conference is a spin off the Atlanta Java User Group.

Here are a few things I like about the conference personally:

  • There is around 10 presentations over two days, so you will be able to see all / most of them.
  • The price is very reasonable ($150 for early birds), $185 regular price.
  • The size is reasonable, so interacting with speakers is natural.
  • Atlanta in March is very nice.
  • ahem, I will be speaking there, ahem.

I will personally speak about our experience in scaling Hibernate in big environments and how SaaS vendors can face the challenge. I will also discuss Hibernate Shards and Hibernate Search with regard to scalability. And there are nine other speakers at the conference, so check their website.


JarInspector on Mac OS X

2008-08-29  |   |  java   Mac OS X  

There is a tiny little utility that let's you inspect JAR/WAR/EAR files on the Mac OS platform. The software is available here. Install it. To open a JAR, simply right click and chose JarInspector as the application. I personally did not set JarInspector as my default .jar application to let the default JAR launcher kicks in but I have been very close to.

Amongst the useful features:

  • navigate in your jars recursively
  • edit/view files (useful for MANIFEST.MF)
  • decompile a class
  • find a file/class by name

By the way, this utility also opens zip files.

Enjoy.


Innovation in the Log space, yawn...

2007-08-01  |   |  java  

Steve and I had a discussion yesterday about loggers. I know what you're thinking: hasn't log been a solved problem for years now? Plus it's boring ;)
That's why usually, when a discussion starts on the subject, I tend to carefully not listen. But because it's Steve, and because he has some specific requirement for the next Hibernate Core version, I decided to ignore my own rule.

It turned out to be much more interesting than what I expected. Here are some news for people, like me, that stopped listening to the log crowd when the rule was use log4j and when you can't use commons-logging.

I was pleasantly surprised by slf4j. I know, it's yet another facade and the name is awful. But this project has 2 features that really caught my attention.

Parameterized log
Isn't it very annoying to have to do

if ( log.isDebugEnabled() ) {
log.debug("My dummy " + object1 + " and expensive " + object2 + " concatenation");
}

because the object's toString() method are expensive?

slf4j solves that by using parameterized logs

log.debug("My dummy {} and expensive {} concatenation", object1, object2);

Very elegant and just as efficient as the previous form. Now because slf4j supports JDK 1.3, the API cannot use varargs, which means that for 3 or more parameters you will have to write

log.debug("My dummy {} and expensive {} concatenation {}", new Object[] { object1, object2, object 3 });


instead of the much more elegant

log.debug("My dummy {} and expensive {} concatenation {}", object1, object2, object3);


Damn slow movers! I guess most of the time you have 1 or 2 arguments so the pain should be minimal, or you could write you own facade, sigh

Static binding

Once I understood what it meant, I liked it. Basically to switch from one underlying logger to another, you will replace slf4j-mylogger1.jar by slf4j-mylogger2.jar: the slf4j engine is statically bound to an implementation.
OMG! This means I cannot change my logger implementation by hot deploying a config file! Oh, wait a minute, it's useless anyway.
The good side is that classloader hells are behind us.

The Ultimate Uber Cool solution

The ultimate solution is actually what Gavin came up with in Seam. So instead of doing

private static final Log log = LogFactory.getLog(CreateOrderAction.class);

public Order createOrder(User user, Product product, int quantity) {
if ( log.isDebugEnabled() ) {
log.debug("Creating new order for user: " + user.username() +
" product: " + product.name()
+ " quantity: " + quantity);
}
return new Order(user, product, quantity);
}

you end up with

@Logger private Log log;

public Order createOrder(User user, Product product, int quantity) {
log.debug("Creating new order for user: #{user.username} product: #{product.name} quantity: #0", quantity);
return new Order(user, product, quantity);
}


Notice the parameterized logs, the log injection (yes the framework is smart enough to guess the category, doh!), and the contextual parameters injection.

But such solution is not accessible to library developers until someone decides to push that into the JDK.
OK I'm done for logs for another 5 years time :)


Google Guice: IoC revisited

2007-03-08  |   |  ioc   java  

Google has made public his IoC container. It's all annotations based, no more strings, no more XML.

Some key concepts:

  • Avoid string based injection which are error prone and hard to refactor
  • @Inject actually inject :-)
  • @ImplementedBy(ServiceImpl.class). A service can have a default implementation, use by default when no wiring is explicit. The actual implementation is easily identified, including by your IDE...
  • Injection through custom annotations (even parameterized): useful when you need to bind 2 services implementations and use one or the other. Also useful to bind constants: Guice allows you to bind a constant to an annotation.
  • Scoping: injections are scoped, and you can create you own scope (transaction). Inner scopes can see outer scopes.
  • Because it's Bob Lee: Guice has integration with AOP Alliance is supported
Here are some examples:
Basic injection
public class Client {
private final Service service;

@Inject
public Client(Service service) {
this.service = service;
}

public void go() {
service.go();
}
}


Default for autowiring
@ImplementedBy(ServiceImpl.class)
public interface Service {
void go();
}

Custom annotations
bind(Service.class)
.annotatedWith(Blue.class)

.to(BlueService.class);

...

@Inject
void injectService(@Blue Service service) {
...
}


What I really like:
  • Annotation based, easy to read and concise
  • Injection on methods (not only setters)
  • @ImplementedBy: Most services, they are implemented one and only one time.

I remember the old days of Pico vs Spring vs Avalon. I'm happy to see innovation flowing again in this field. Some took for granted that Spring was the only way, then come annotations. JBoss Seam and its annotation based stateful injection / outjection, and now Google Guice: both share some of the interesting concepts I described earlier. Component injection is revisited and it's good.

Now remember, IoC is not application development, it's at best a part of it :-). To me, the programmation model with the biggest/homogeneous picture is JBoss Seam.


ActiveRecord pattern, so what?

2007-01-07  |   |  grails   java   persistence  

The Active Record pattern has a lot of publicity recently thanks to the Ruby On Rails and Grails wave. A definition could be: an object that encapsulates both data and behavior (ie a database row and it's data access logic).

A bit of history
I was asked recently my thoughts about this pattern. First of all, if someone still remembers EJB 1.0 and 2.x Entity Beans, this was a perfect example of the Active Record Pattern... and a successful failure. Some of the reasons for this failure was the tight link between the data and it's access logic: Serialization issue, data tight to a persistent technology etc etc.

Statically typed languages
To me the ActiveRecord pattern is not well suited for statically typed languages like Java, hence the raise of another pattern : DAO (aka DAL in the .net world). It prevents the hard link between the persistence technology and the actual data representation.

Dynamic languages
Dynamic languages (and to a certain extend AOP) have the nice ability to decorate an object with additional features on the fly, without linking it "the hard way": you can then easily reuse your domain classes out of the persistence context.
Grails uses such a behavior to add CRUD operations transparently to your domain model (with quite complex Querying capabilities).
One still face a problem, what if the application developer needs to add a more complex persistence operation (esp a query), he will end up "hard-coding" the function to the domain object and we're back to the issue faced by statically typed languages... unless you create a DAO object. But then, your persistence operations will be split between your implicit domain model methods and your DAO: another code smell.

Dynamic DAO
As you can see, I'm not keen on the ActiveRecord pattern (out of simple applications), but I really love the simplicity of GORM (the Grails way). The solution is a dynamic DAO. JBoss Seam already generates very simple yet powerful DAOs benefiting from Java Generics. If you combine that with a dynamic language, you can have the best of both worlds.

class UserProcess {
@In UserDao userDao;

void create(String firstname, String lastname) {
if (userDao.countByFirstnameAndLastname(firstname, lastname) == 0) {
def user = new User( "Emmanuel", "Bernard" )
userDao.save user
}
else {
throw new UserAlreadyExistException()
}
}
}


Note that countByFirstnameAndLastname and save can be dynamic methods à la GORM.

Conclusion
I'm not a big fan of the ActiveRecord. For static languages, I would use the DAO approach. For dynamic languages, I did not make up my mind but a DAO on steroids seems very promising.


Name: Emmanuel Bernard
Bio tags: French, Open Source actor, Hibernate, (No)SQL, JCP, JBoss, Snowboard, Economy
Employer: JBoss by Red Hat
Resume: LinkedIn
Team blog: in.relation.to
Personal blog: No relation to
Microblog: Twitter, Google+
Geoloc: Paris, France

Tags