XPages Custom Converters: Change the data, Change the world!

So as my next installment of the XPages feature series I will be discussing Converters, This seemingly boring feature actually has a lot of functionality packed into it.  Almost everyone who has ever written an xpage has probably used at least one of the standard converters that come out of the box.  I would say the most used one is the date converter.  An example of a simple date control with a datepicker looks like this:

<xp:inputText id=”inputText1″>
<xp:this.converter>
<xp:convertDateTime type=”date”></xp:convertDateTime>
</xp:this.converter>
<xp:dateTimeHelper></xp:dateTimeHelper>
</xp:inputText>

As you can see there it is, right in the middle, a date converter.  Simple enough to use but what does a converter “really” do.  It converts data right, well what does it convert it from and to and why does it need to convert it.  So in the example above its converting the data between the HTML markup and the JSF component tree.  In the component tree the data is stored as a Notes DateTime object that when written out using its toString method writes out the date and time in a very long format.  This converter formats it for the html that gets sent to the page so it looks however the end user wants it.  However that is not all that it does, it also does the reverse when the form is submitted on the page it has to convert it back from the format the developer picked to a NotesDateTime object.

So that’s cool and all, but Isn’t this just really a formatter for different types of data, dates, currency and such.  Well the answer is not really is actually a lot more powerful then that when you think about it.  Yes that is most of what XPages comes with out of the box, but a developer can write their own converters and that is where the you see the power of converters.

Let me give you an example of how you can use converters in a way that’s not just formatting.  Let’s say you have some data in your database that you would like to be encrypted for all users except for a certain role, Its very easy to write 2 methods getAsString and getAsObject inside your custom converter so that this happens.  The data inside your database is always encrypted, but then if the user has the correct role the getAsString method could convert the data into plaintext, when they submit it the possibly new value gets encrypted again before it goes back into the database.

Using a converter this way helps separate the conversion of any field to an encrypted field into a single manageable module that can be applied easily.  Another fun way to use converters is to help convert an id that is stored in a document to a lookup value stored in a lookup document. So you could have “USA” stored in each of your main documents but then display “United States of America” from your lookup document and convert it back to ensure the correct thing is stored in the database.  It is really easily to write a custom converter.  There are 2 methods you must implement when you implement the javax.faces.convert.Converter interface.

1.  public Object getAsObject(FacesContext facesContext, UIComponent component, String value) :

This method is called after a form is submitted from the xpage it is passed in the current facesContext object, the component the component is setup on and the value of that component as a String.  This is where you would take the unencrypted value and encrypt it before it gets saved to the database in our example.

2.  public String getAsString(FacesContext facesContext, UIComponent component, Object value):

This method is just the reverse, it builds out the object that is coming from the component tree and gets it ready for the html markup.  In our example this is the method that would check the role of the end user and then either decrypt the data or return back a value to alert the user that they don’t access to the encrypted field.

So once you have this class built you need to do 2 additional steps.

1.  Add the class to the faces-config as a converter, similar to a managed bean this simple declaration just gives the converter a unique id to use on the component where you wish to convert the value.

<faces-config><converter> <description>A Converter for encrypting fields</description><converter-id>customConverter</converter-id> <converter-class> com.tobysamples.converters.EncryptionConverter </converter-class> </converter></faces-config>

2.  You must apply the converter to the component that needs conversion.

<xp:inputText id=”inputText1″>
<xp:this.converter>
<xp:converter converterId=”customConverter”></xp:converter>
</xp:this.converter>
</xp:inputText>

you notice the converterId attribute on the component matches the faces-config value as well.

Thats really it, pretty easy to use and use on all your xpages.  If stored inside of an OSGi plugin you could use it on all of your applications.

I think this feature of XPages speaks to a larger point inside of the environment.  XPages is broken into many pieces for a good reason, it helps us as developers separate our code out in a way that’s reusable and inheritable.  Over time, this ideology will save you time as you won’t be rewriting the same functionality or even copy and pasting it.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s