Posts

Showing posts from 2010

Persisting ViewScoped beans across views in request

I came across this problem when trying to deal with view scoped beans that you want to reuse in a different view, i.e. after clicking next in a wizard like page.

This was originally Discussed Here (now removed since Oracle merged Sun's forums).

The View Scope
There is a a brief summary of it here: JSF 2.0 New Feature Preview Series (Part 5) EDR1 Potpourri.
Basically view scoped values are attached to the current viewId. Values for the view scoped variables are stored in the map returned by UIViewRoot.getViewMap(boolean). Which is great for when your accessing the same view. However, it is cleared when the view is changed (e.g. from a navigation result) FacesContext.setViewRoot(javax.faces.component.UIViewRoot)

However, the flash scope was designed seemingly to solve this very problem.

Using the Flash Scope
Here's a write up of the Understanding the JSF 2.0 Flash scope. There's also some caveats shown here: The benefits and pitfalls of @ViewScoped.
So the logical step is to t…

f:convertNumber parses to double not BigDecimal

The default behaviour of the f:convertNumber, implemented with NumberConverter, in converting a decimal String of "1.11", is to convert it to a double and then JSF converts that to a BigDecimal. Most of the time you won't notice this happening until you use CallableStatement.setBigDecimal to invoke a stored procedure. In MS SQL Server, you get the following error:
com.microsoft.sqlserver.jdbc.SQLServerException: Error converting data type nvarchar to decimal.The cause of this is because inside the BigDecimal it stored "1100000000000000976996261670137755572795867919921875" as a result of converting the String to a double. This floating point error is the motivation for using BigDecimal in the first place. And of course because the SQL Server JDBC driver didn't know how to handle the BigDecimal properly.

Looking into ConvertNumber, it uses one of two converters (DecimalFormat or NumberFormat) depending on whether 'pattern' is used. In Java 5, they adde…

Fixing my HTC Desire's wifi

I recently did an Over The Air (OTA) update of my new HTC Desire from 2.09 to 2.10. The update all seemed to run correctly. However I soon noticed that the wifi wasn't working. Looking in settings, it showed wifi was disabled and when you try and enable it, you just get "error". Seems like other people have been getting this as well. I tried following their advice, reset the factory defaults but that didn't work. I couldn't get the recovery mode to load (in order to wipe the caches) - after some brief searching it appeared that this was due to root access so I gave up on that.
NOTE: it turns out I was doing it wrong. After selecting the recovery option a red triangle with an exclamation point is show. At which point you need to press volume+ and power to show the next menu.

Next I tried using latest RUU (2.10) but got Error 170 Usb Connection Error. One post mentions under 'update':
HTC has released a new Froyo OTA update. You can install this directly as…

Escaping a regex expression

I was working on a project where I needed to dynamically generate a regular expression based on some user input but the string to search for needed to be escaped. Below is the quick and dirty way to do it:
/** * Utility function to replace regular expressions. * * @param input * @return */ private static String escapeRegex(String input) { String special[] = { "\\", "[", "]", "^", "$", ".", "|", "?", "*", "+", "(", ")" }; String val = input; for (String replace : special) { val = val.replace(replace, "\\" + replace); } return val; }

Tomcat DBCP: Data source is closed

After updating to the latest version of Tomcat I started getting the following error when redeploying a webapp from inside eclipse:
java.sql.SQLException: Data source is closed     at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1362)     at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
It seemed to be related to an updated version of DBCP that is used inside tomcat (I get Tomcat to manage my datasource). After tracing the code a bit I discovered it was because I called this, in my Filter.destroy() to do clean up:
((BasicDataSource) dataSource).close();
Older versions of Tomcat (6.0.26 and below), didn't care if you called it. When the webapp was reloaded, the datasource still worked. But as of 6.0.28, the newer version of DBCP seems to cause problems.

So if you want to clean up after the webapp, use the removeAbandoned attribute in the Tomcat Configuration on the datasource, that way DBCP just cleans up aft…

Portable java environments on windows

I always seem to be copying my development environment between PCs and latops which end up being time consuming. Its not the size of the data, its the number of small files (mainly javadoc & java source) that slow the whole process down. I already store the source code and workspace for my clients in a TrueCrypt Volume, to prevent my code being stolen if someone were to get hold of my laptop.

All the other necessary files I need for development; such as libraries, jdk, tomcat/jboss, elcipse etc; are stored on my hard drive. In some cases on different drive letters on different computers. So to simplify this I wanted to store them in a similar way to a TrueCrypt volume but without the overhead of encryption and the hassle of mounting it. After some poking around I remember that Windows 7 came with built-in support for creating and mounting Virtual Hard Disk (VHD) straight from the Storage Manager. The VHD are used by Virtual PC. For those running Vista, Virtual PC 2007 should suppo…

EL Coerces empty/null to ZERO

I recently came across a problem where I was expecting a null value to be populated into one of my JSF managed beans on submit. After digging through the entire stack, I found out this was deliberate.
This bug was introduced into Tomcat 6.0.16, as a consequence of implementing the EL spec to the letter.
The option to disable this change at command line was added in 6.0.17:
-Dorg.apache.el.parser.COERCE_TO_ZERO=false
A patch in Tomcat 6.0.24 was added to allow you to change it at run time:
System.getProperties().put("org.apache.el.parser.COERCE_TO_ZERO", "false");
This problem also directly occurs in JSF, as it uses an EL engine as well. There's a patch for 1.2_08-b01 but it is happening in 2.0.2. But the above fix seems to work.
Request to change the JSP Spec
As per chapter 1.18.2 and 1.18.3 of EL spec, EL coerces null values to non-null
values such as empty String or (Long) 0 or (Boolean) false. This behaviour is in
almost all cases unwanted when the type is not a…

A simple way to Inject Guice into JSF (Mojarra)

Previously I have been using GuiceSF to inject the JSF managed beans which extends the Mojarra's implementation of ELResolver (ManagedBeanELResolver). This was bit of a hack but it was relatively simple to implement.
In upgrading to newer version of JSF, I had to manually tweak it to keep it in line with the new features in the spec which took a fair amount of debug stepping. So when JSF 2 came out I looked around for a way to do it which still used the implementation's bean creation and handling but also injected it with Guice.

After digging around in the injection code in Mojarra, I saw how simple it would be to extend the provided Tomcat injection (which injects stuff for the @Resource and @EJB etc annotations).

This solution first requires the injection provider be specified in web.xml:
<context-param> <description>JSF Injection provider</description> <param-name>com.sun.faces.injectionProvider</param-name> <param-value>net.devgr…

Converting custom JSF 1 components to JSF 2

These are just some observations/tips I made when converting my JSF 1 components to JSF 2.

Simpler .taglib.xmlThe taglib definition changes from mycomponent.tld to mycomponent.taglib.xml. The xml inside the new file is similar but with some changes (i.e. <name> becomes <tag-name>). The major simplification is that attributes no longer need to be defined. Just the tag-name and component-type.
<tag> <name>menuItem</name> <tag-class>net.devgrok.component.MenuItemTag</tag-class> <body-content>JSP</body-content> <attribute> <name>value</name> <required>false</required> <deferred-value> <type>java.lang.String</type> </deferred-value> </attribute> </tag>Becomes:
<tag> <tag-name>menuItem</tag-name> <component> <component-type>net.devgrok.MenuItem</component-type> </component> </tag>And the newly created xml fi…

ClassNotFoundException destroying a session in Tomcat

When a session was being expired (either through a timeout, or via using the Tomcat Manager to manually destroy them) that contained an EJB I was getting a ClassNotFoundException. The stack trace when killing from the manager was:
java.lang.RuntimeException: Specified calling class, net.devgrok.MyEjbRemote could not be found for WebappClassLoader delegate: false repositories: ----------> Parent Classloader: org.apache.catalina.loader.StandardClassLoader@70cb6009 at org.jboss.ejb3.common.lang.SerializableMethod.getClassFromName(SerializableMethod.java:311) at org.jboss.ejb3.common.lang.SerializableMethod.getClassType(SerializableMethod.java:282) at org.jboss.ejb3.common.lang.SerializableMethod.toMethod(SerializableMethod.java:233) at org.jboss.ejb3.common.lang.SerializableMethod.toMethod(SerializableMethod.java:220) at org.jboss.ejb3.proxy.impl.handler.session.SessionProxyInvocationHandlerBase.invoke(SessionProxyInvocationHandlerBase.java:182) at org.jboss.ejb3.proxy.impl.…

Using RichFaces to give versioned URL's

RichFaces has some nice components that can load scripts and styles when placed anywhere in the xhtml page and automatically inserts them into the header at render time. For example a footer could say it requires stylesheet, after you've already defined a header.

The tags are pretty simple there is the style loader, loadStyle:
<afj:loadstyle src="/css/test.css"></afj:loadstyle>And the script loader, loadScript:
<afj:loadscript src="/javascript/test.js">
The src can be a path be:
Relative to the current page.Path relative to the context if starting with a slash.Or loaded by RichFaces resource framework
Using "resource:///path/to/file"Now, the problem most web developers always face is that of caching. If you disable caching then the site is slow for the user and your bandwidth is used up. If you enable caching and release a new version, how do you clear the user's and ISP's cache so they can see your changes?

RichFaces already d…

Safari removed javascript API

In the latest version of Safari (WebKit) they have removed some deprecated javascript API & tags which can cause problems with older code. This is my attempt to keep track of them so I can search through the code and change it to use a newer method.

Here is a list of what works in Firefox 3 or Internet Explorer but not Safari:

document.[form name] where [form name] matches the element <form name='[form name]'>
Replacement:Use document.getElementById() insteaddocument.embeds
Replacement:
Use document.getElementById() insteadForm element's id defaulted to their name
Replacement:
Manually specify the id<applet> tag
Replacement:
<object> tagThat's it for the moment but I'll keep updating the list as I find them.

Building your own jbossall-client.jar

The newer versions of JBoss (I'm using 5.1.0 GA) very annoyingly have all the client jars split into at least 47 separate jars! Which is a bit rude when you consider the total number of jars they expect you to copy into your tomcat/lib dir is a whopping 93.

JBoss are declined to make the client jars into a single file again as its meant to make it easier to upgrade... That's arguable but still leaves us with all these files to copy around. After searching the net I've found a rather nice solution which I have adapted below.
The way I use it is as follows. I combine all jboss*.jar files into a single jar and then copy the additional dependencies.

Create a directory an empty directory and put the build.xml in it and create a /jboss dir. Copy all jboss jboss*.jar from jboss-5.1.0.GA/client.

Create a /build.xml:
<project default="combine"> <property name="temp.dir" value="unpacked" /> <property name="lib.dir" value=&q…

Automake unable to detect vendor on RedHat EL5

After chasing down some build problems with subversion 1.6.9 on EL5 I was noticing that it was detecting the system as x86_65-unknown-linux-gnu. Worried that it would cause me later problems I started digging through the configure script. It lead me to the build/config.guess script.
After spending too long searching the net and trying to resolve the issue, I just did this:
subversion-1.6.9>cp /usr/lib/rpm/config.guess ./build/config.guessBasically overriding the one that came with the distro with redhat's hack.

Using a NavigiationHandler to do HTTP/HTTPS switching

In a project I was working on, we wanted the log in page and anything to do with payment to be secure using HTTPS, whilst the majority of the site would be unsecure using HTTP. JSF 1.2 doesn't really give you anyway of doing this other than manually specifying the full url for every single link and button on the site. This removes a lot of the flexibility and simplicity of JSF. I came up with a pretty good solution. For any link or action that you know will switch between secure and unsecure, which isn't that hard to know (if you design the site with that in mind), then you configure it to be a redirect. Then you create your own navigation handler which applies rules you create yourself, to determine which parts should be secure or not.

This is a very simple solution that when a redirect occurs, it checks the path of the destination page (its viewId). If it starts with "/secure" it gives a full HTTPS url and for all others, it gives a full HTTP url. To activate it, h…

Updating the nextval of all sequences in PostgreSQL

If you've been doing SQL level inserts for testing purposes, then when you go to use the sequences then they will have a nextval that already exists in your table.

So below is a script which updates the nextval for all fields that were created using bigserial/serial:
/* Updates all the sequences to have a next value of max+1 excluding the list passed */ CREATE OR REPLACE FUNCTION fn_fixsequences(excludes text) RETURNS integer AS $BODY$ DECLARE themax BIGINT; mytables RECORD; num integer; BEGIN num := 0; FOR mytables IN select relname, ns.nspname, a.attname, pg_get_serial_sequence(c.relname, a.attname) as seq FROM pg_catalog.pg_attribute a INNER JOIN pg_catalog.pg_class c ON c.oid=a.attrelid inner join pg_catalog.pg_attrdef d on d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef LEFT JOIN pg_catalog.pg_namespace ns ON ns.oid = c.relnamespace WHERE pg_catalog.pg_table_is_visible(c.oid) and a.attnum > 0 AND NOT a.attisdropped and attt…

Getting JBoss Scheduler working

When using the @Service annotation together with the scheduler has given me no end of trouble so I'd like to share my working configuration.

It took me a while to get the objectName right. If your not using @Service(objectName='name') but instead using @Service(name='name') then the final object name is not the same as what they imply at EJB Extensions Help.
Instead I'd recommend going into the JMX console of the running server and searching for it manually, listed under 'jboss.j2ee' for the name you've specified AND type=ManagementInterface.

As well as defining the @Service, you'll also need to define the @Management.

@Management(SampleServiceMBean.class) @Service(name = SampleServiceMBean.SERVICE_NAME) public class SampleServiceMBean implements SampleService { public final static String SERVICE_NAME = "SampleServiceMBean"; public void process(ObjectName name, Date date) { log.info("process {} {}", name, date); }
The…

Disabling RichFaces FacesBeanValidator

If you use the rich:ajaxValidator, for example:
<rich:ajaxValidator event="onblur" /> It automatically adds a FacesBeanValidator to the components list of validators. If you don't have javax.validation or Hibernate Validator setup then you'll get the following exception:
2010-01-07 00:29:19,889 [http-8443-1] WARN org.richfaces.validator.ObjectValidator - Hibernate Validator could not be instantiated, use stub instead javax.validation.ValidationException: Unable to find a default provider at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:248) at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:115) at org.richfaces.validator.BeanValidator.(BeanValidator.java:34) at org.richfaces.validator.ObjectValidator.createInstance(ObjectValidator.java:54) at org.richfaces.validator.ObjectValidator.getInstance(ObjectValidator.java:85) at org.richfaces.validator.FacesBeanValidator.validate(FacesBeanValidator.java:103) …