Help

The Web Beans specification defines an XML configuration format that uses XML namespaces to achieve typesafety.

Imagine that we have the following class:

public class ShoppingCart {
    
    private final PaymentProcessor paymentProcessor;
    private final User customer;
    
    public ShoppingCart(PaymentProcessor paymentProcessor, User customer) { 
        this.paymentProcessor = paymentProcessor;
        customer = customer;
    }

    ...

}

Of course, we could configure its scope, name and dependencies using annotations:

@SessionScoped
@Named("cart")
public class ShoppingCart {
    
    private final PaymentProcessor paymentProcessor;
    private final User customer;
    
    @Initializer
    public ShoppingCart(@PayBy(CREDIT_CARD) PaymentProcessor paymentProcessor, @LoggedIn User customer) { 
        this.paymentProcessor = paymentProcessor;
        customer = customer;
    }

    ...

}

But suppose that this class is defined in a reusable library, and that this metadata depends upon the application in which it is deployed. Then it would be better to define the metadata in XML. The Web Beans Early Draft defined a configuration format that was similar to other Java EE deployment descriptors:

<web-beans ...>

   <component>

      <class>org.example.ShoppingCart</class>
      <named>cart</named>
      <scope>javax.webbeans.SessionScoped</scope>

      <constructor>
         <param>
            <type>org.example.PaymentProcessor</type>
            <binding>org.example.PayBy(CREDIT_CARD)</binding>
         </param>
         <param>
            <type>org.example.User</type>
            <binding>org.example.LoggedIn</binding>
         </param>
      </constructor>

   </component>

</web-beans>

There are several problems with this approach:

  • it's quite verbose
  • the interesting information (the type names) can't be validated against an XML schema
  • the interesting information can't be autocompleted without special tooling that is aware of the Java types

Even worse, the XML format places a bit too much emphasis upon the actual Java constructs (constructor, param, etc) which is inappropriate if the use case is configuration of a third-party library.

Therefore, the Web Beans public draft defines a different approach, inspired by Spring 2 and Seam 2. The idea is to define an XML namespace corresponding to each Java package. For example, the namespace urn:java:org.example represents the Java package org.example. XML elements in this namespace represent types or members of types in that package.

We can re-write our example as follows:

<WebBeans xmlns="urn:java:javax.webbeans"
          xmlns:eg="urn:java:org.example">

   <eg:ShoppingCart>
      <Named>cart</Named>
      <SessionScoped/>
      
      <eg:PaymentProcessor>
         <eg:PayBy>CREDIT_CARD<eg:PayBy>
      </eg:PaymentProcessor>
      
      <eg:User>
         <eg:LoggedIn/>
      </eg:User>
      
   </eg:ShoppingCart>
   
</WebBeans>

Now, what's really fantastic about this approach is that we can write an XML schema for each namespace, letting us take advantage of autocompletion and validation when we write the XML document. Even better, the RI project plans to create a Java 6 annotation processor (a compiler plugin for javac) that automatically generates this schema as part of the compilation process. So every time you compile your code, you'll immediately see any resulting errors in your XML configurations! Thus, this approach tackles one of the main causes of the XML hell that affects Java development.

Personally, I'm pretty bewitched by any solution which is simultaneously more typesafe and less verbose (usually typesafety costs in verbosity). However, at least one of the members of the Web Beans EG is concerned that the typesafe XML format is inconsistent with the format used by other Java EE deployment descriptors, and potentially confusing.

Therefore, I would like to gather feedback from the community on this issue. Which style do you prefer? Please let us know what you think in comments.

18 comments:
 
21. Dec 2008, 14:59 CET | Link
Andrew Lee Rubinger | alr(AT)jboss.org

Let's ditch the older conventions in favor of compile-time typesafe checking. If successful I'd love to see this make it into a future rev of the EJB spec, for example.

S, ALR

ReplyQuote
 
21. Dec 2008, 15:52 CET | Link
Even better, the RI project plans to create a Java 6 annotation processor (a compiler plugin for javac) that automatically generates this schema as part of the compilation process. So every time you compile your code, you'll immediately see any resulting errors in your XML configurations! Thus, this approach tackles one of the main causes of the "XML hell" that affects Java development.

Will that approach imply that only web-beans.xml will actually be parsed for informations during app initialization not annotations?

 
21. Dec 2008, 15:58 CET | Link
Will that approach imply that only web-beans.xml will actually be parsed for informations during app initialization not annotations?

No. I'm not quite sure what you're getting at.

 
21. Dec 2008, 16:05 CET | Link

My understanding is that you intend to create a web-beans-xml during compilation every time, right? I think that this might override any informations made with annotations for the discover process. So is there any necessarity to scan for them?

 
21. Dec 2008, 16:09 CET | Link
Benjamin wrote on Dec 21, 2008 10:05:
My understanding is that you intend to create a web-beans-xml during compilation every time, right? I think that this might override any informations made with annotations for the discover process. So is there any necessarity to scan for them?

No, I'm creating an XML schema that tells any XML parser or editor exactly what elements exist in the namespace that represents the Java package, thereby allowing the developer to more easily author the web-beans.xml file.

 
21. Dec 2008, 16:12 CET | Link

Okay! Now I get it. :-) Good idea!

 
21. Dec 2008, 17:40 CET | Link

Your suggested approach has no drawbacks as far as I can see. Typesafety should be kept - it is an essential feature for fast error handling and it makes it so much easier for tooling to focus on the more interesting harder problems than validating j2ee spec files. It is one of the biggest failures of the older j2ee spec to rely on IDE tools to help create configuration files. Framework specific tools should be a helping hand that allows you to go further than the basis, it should not be a necessary requirement to simply start using framework.

 

--max

 
21. Dec 2008, 18:03 CET | Link

One issue that might be relevant to at least outline how should be handled is versioning/naming of the schema files so a tool can know which xsd to pick up. Using the same xsd location for all versions would be bad i think.

Those XSD validating tools I know uses the xsd location/name to locate the schema to validate against and if you have multiple versions of your project in your IDE (which you will have over time), the tool either need to know how to use different xsd locations per project or the files will need to use different xsd names/versions. The latter is what tools supports today.

 

--max

 
21. Dec 2008, 18:29 CET | Link

Why wouldn't you just generate the XSD into the same output location as the classes?

 
22. Dec 2008, 08:37 CET | Link
Erik Mattheis | erik.w.mattheis(AT)espn.com

I don't feel like there's 100% consistency among the various XML descriptors in the J2EE platform today. There are always little quirks between different descriptors and how containers handle them, and a lot of the interesting stuff is in container-specific descriptors anyway. My point being that developers already have to contend with these issues and refer to documentation, so the idea of keeping future XML descriptors 'consistent' is a poor rationale against a radical shift. The schema-driven idea set forth in the Web Beans draft makes a lot of sense to me, and seems a lot more natural than the present J2EE style descriptors. Add to that type-safety and the ability to leverage existing tooling support for XML and you have a win-win(-win?) situation.

 
22. Dec 2008, 14:45 CET | Link
Gavin King wrote on Dec 21, 2008 12:29:
Why wouldn't you just generate the XSD into the same output location as the classes?

sure, but it is not the generation destination that is the problem, it is which XSD the tool will pick up when it see's the xsd reference. The tool would need to know how to lookup the XSD via the classpath somehow instead of via normal means of resolving an xsd reference to an url (or possibly cached version)

 

--max

 
22. Dec 2008, 15:02 CET | Link

Max, that's a great point. So should the spec define a URI for the XSD, and that the Web Beans implementation uses a certain EntityResolver to resolve URIs of that format in the classpath?

I think it's a great idea. It would let you portably package the XSD in your deployment archive.

 
22. Dec 2008, 17:31 CET | Link
Gavin King wrote on Dec 22, 2008 09:02:
Max, that's a great point. So should the spec define a URI for the XSD, and that the Web Beans implementation uses a certain EntityResolver to resolve URIs of that format in the classpath?

Could you give an example ? something like classpath://com.bigbuckscompany.model/shoppingcart.xsd as opposed to http://www.bigbuckscompany.com/xsd/shoppingcart.xsd ?

I think it's a great idea. It would let you portably package the XSD in your deployment archive.

I guess it would at least allow tooling to be better; something that would be hard with plain http uri's where you would have to use something like version as part of the name.

It would not help in classic xml editors though.

Will need to experiment a bit to see how well it works.

 

--max

 
22. Dec 2008, 17:46 CET | Link
Could you give an example ?

Dunno, what exactly constitutes a valid schemaLocation? Are we allowed to invent our own protocols? Do you even need to explicitly specify a schemaLocation, or is there some way to write some kind of Resolver based purely on the namespace? (I don't know of anything like that, only EntityResolver.)

It would not help in "classic" xml editors though.

Yes, that's an issue. So then should we make the "standard" location a URL, so that you could place the (generated) schema there if you wanted "classic" editor support?

i.e. we could standardize that the schema for the Java package org.example.foo should live at the URL http://example.org/foo/schema.xsd and at /org/example/foo/schema.xsd in the classpath. Then the EntityResolver in Web Beans-aware tooling would know to load it from that location in the classpath, and other tooling could load it from the URL.

It would be even better if the resolver could be aware of the namespace urn: and figure out the XSD location based upon that, but I don't know of a way to implement that...

 
22. Dec 2008, 18:09 CET | Link

According to Pete, this is the answer:

 
22. Dec 2008, 22:43 CET | Link
Chris Bredesen | cbredesen(AT)redhat.com

I certainly prefer this proposal to existing XML formats. However, when you consider the potential mound of schema references in the file, it may not actually be less verbose. True, the schema references are header data and the meat of the file is far more readable, but you've kinda traded one form of verbosity for another. I don't fear this change at all, it's better use of the medium IMO.

 
31. Dec 2008, 21:07 CET | Link
AndyT (lordpixel)

I would have thought this is a perfect use case for XML Catalogs, which in Java pretty much means Norman Walsh's Catalog Resolver.

I've used this pretty extensively with DOM and I think it works with SAX and XSLT (i.e. its widely supported) too.

I'm not familiar with the whole org.w3c.dom.ls package, and so there may be a reason to prefer LSResourceResolver, but I'd check to see if CatalogResolver is sufficient because it works well. Also because Catalogs are an OASIS standard other non-Java tools can parse them too.

 
31. Dec 2008, 21:16 CET | Link
AndyT (lordpixel)

The typesafe, namespaced XML is far better... there's just no contest. It is more descriptive, more toolable and shorter. It is also not a revolutionary idea - as you point out Spring and Seam implemented this and proved it works. JEE shouldn't jump on every fad, but nor should it mire itself in techniques that are years out of date.

I have one concern... I hear you about not wanting to write Java code in XML (<constructor>, <class> etc), but the new format is almost too implicit:

<eg:ShoppingCart>
      <Named>cart</Named>
      <SessionScoped/>
      
      <eg:PaymentProcessor>
         <eg:PayBy>CREDIT_CARD<eg:PayBy>
      </eg:PaymentProcessor>
      
      <eg:User>
         <eg:LoggedIn/>
      </eg:User>
      
   </eg:ShoppingCart>

There's nothing in that XML that tells me what <eg:PaymentProcessor> or <eg:User> are for. I just have to know they are initializer arguments. Actually, there's not even anything that tells me they are related in any way (well, they're not related per se, but they are in the sense they're an argument list).

So maybe just a little more verbosity for the sake of clarity?

<eg:ShoppingCart>
      <Named>cart</Named>
      <SessionScoped/>
      
<initializer>
      <eg:PaymentProcessor>
         <eg:PayBy>CREDIT_CARD<eg:PayBy>
      </eg:PaymentProcessor>
      
      <eg:User>
         <eg:LoggedIn/>
      </eg:User>
</initializer>      
   </eg:ShoppingCart>

No need to go as far as making it

<initializer> <params> ... </params> </initializer>

but at least giving the reader a clue?

Post Comment