<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8492059842142356488</id><updated>2012-02-20T11:24:57.455-08:00</updated><category term='Atmosphere'/><category term='PrimeFaces'/><category term='jQuery'/><category term='GWT'/><category term='CSS'/><category term='Subversion'/><category term='Apache POI'/><category term='JSTL'/><category term='Java'/><category term='Test'/><category term='Ajax'/><category term='Web'/><category term='Raphaël'/><category term='Java-Plugin'/><category term='Maven'/><category term='JCR'/><category term='Linux'/><category term='Validation'/><category term='PrimeFaces Extensions'/><category term='MyFaces'/><category term='JSF'/><category term='Jackrabbit'/><category term='Facelets'/><category term='JavaScript'/><category term='JSON'/><category term='Comet'/><category term='Jersey'/><category term='PowerMock'/><category term='HTML5'/><title type='text'>Thoughts on software development</title><subtitle type='html'>"The best is yet to come"</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>66</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-6465814942766294817</id><published>2012-02-17T07:36:00.001-08:00</published><updated>2012-02-18T00:43:27.033-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Advanced injection of Maven properties into Java application</title><content type='html'>In the &lt;a href="http://ovaraksin.blogspot.com/2012/02/inject-maven-project-informations-into.html"&gt;last post&lt;/a&gt; I have shown how to inject Maven project informations into Java application. This topic describes the injection for more useful properties. Advantage: no needs to define then any project specific Java constants and change constants with each release. Current project infos already exist in &lt;span style="color: orange;"&gt;pom.xml&lt;/span&gt;. In the &lt;a href="http://code.google.com/p/primefaces-extensions/"&gt;PrimeFaces Extensions project &lt;/a&gt;we have defined some profile dependent properties like these&lt;br /&gt;&lt;pre class="brush:xml"&gt;...&lt;br /&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;org.primefaces&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;primefaces&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;${primefaces.core.version}&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt; &lt;br /&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;org.primefaces.extensions&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;primefaces-extensions&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;${pe.impl.version}&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;properties&amp;gt;&lt;br /&gt;    &amp;lt;java.version.source&amp;gt;1.6&amp;lt;/java.version.source&amp;gt;&lt;br /&gt;    &amp;lt;java.version.target&amp;gt;1.6&amp;lt;/java.version.target&amp;gt;&lt;br /&gt;    &amp;lt;jetty.server.version&amp;gt;8.1.0.RC2&amp;lt;/jetty.server.version&amp;gt;&lt;br /&gt;    &amp;lt;pe.jsf.impl&amp;gt;mojarra&amp;lt;/pe.jsf.impl&amp;gt;&lt;br /&gt;    &amp;lt;pe.jsf.displayname&amp;gt;Mojarra&amp;lt;/pe.jsf.displayname&amp;gt;&lt;br /&gt;    &amp;lt;pe.jsf.group&amp;gt;com.sun.faces&amp;lt;/pe.jsf.group&amp;gt;&lt;br /&gt;    &amp;lt;pe.jsf.artifact&amp;gt;jsf&amp;lt;/pe.jsf.artifact&amp;gt;&lt;br /&gt;    &amp;lt;pe.jsf.version&amp;gt;2.1.6&amp;lt;/pe.jsf.version&amp;gt;&lt;br /&gt;    &amp;lt;pe.impl.version&amp;gt;0.3.0-SNAPSHOT&amp;lt;/pe.impl.version&amp;gt;        &lt;br /&gt;    &amp;lt;pe.webapp.filter&amp;gt;development&amp;lt;/pe.webapp.filter&amp;gt;&lt;br /&gt;    &amp;lt;pe.webapp.online&amp;gt;false&amp;lt;/pe.webapp.online&amp;gt;&lt;br /&gt;    &amp;lt;primefaces.core.version&amp;gt;3.1.1&amp;lt;/primefaces.core.version&amp;gt;&lt;br /&gt;    &amp;lt;primefaces.theme.version&amp;gt;1.0.3&amp;lt;/primefaces.theme.version&amp;gt;&lt;br /&gt;&amp;lt;/properties&amp;gt;&lt;br /&gt;&lt;/pre&gt;And we also configured two Maven plugins which put more useful properties to Maven based applications.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;plugin&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;com.google.code.maven-svn-revision-number-plugin&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;maven-svn-revision-number-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;1.7&amp;lt;/version&amp;gt;&lt;br /&gt;    &amp;lt;executions&amp;gt;&lt;br /&gt;        &amp;lt;execution&amp;gt;&lt;br /&gt;            &amp;lt;goals&amp;gt;&lt;br /&gt;                &amp;lt;goal&amp;gt;revision&amp;lt;/goal&amp;gt;&lt;br /&gt;            &amp;lt;/goals&amp;gt;&lt;br /&gt;        &amp;lt;/execution&amp;gt;&lt;br /&gt;    &amp;lt;/executions&amp;gt;&lt;br /&gt;    &amp;lt;configuration&amp;gt;&lt;br /&gt;        &amp;lt;entries&amp;gt;&lt;br /&gt;            &amp;lt;entry&amp;gt;&lt;br /&gt;                &amp;lt;prefix&amp;gt;svn&amp;lt;/prefix&amp;gt;&lt;br /&gt;            &amp;lt;/entry&amp;gt;&lt;br /&gt;        &amp;lt;/entries&amp;gt;&lt;br /&gt;    &amp;lt;/configuration&amp;gt;                    &lt;br /&gt;&amp;lt;/plugin&amp;gt;&lt;br /&gt;&amp;lt;plugin&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;buildnumber-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;    &amp;lt;executions&amp;gt;&lt;br /&gt;        &amp;lt;execution&amp;gt;&lt;br /&gt;            &amp;lt;id&amp;gt;generate-timestamp&amp;lt;/id&amp;gt;&lt;br /&gt;            &amp;lt;phase&amp;gt;validate&amp;lt;/phase&amp;gt;&lt;br /&gt;            &amp;lt;goals&amp;gt;&lt;br /&gt;                &amp;lt;goal&amp;gt;create-timestamp&amp;lt;/goal&amp;gt;&lt;br /&gt;            &amp;lt;/goals&amp;gt;&lt;br /&gt;        &amp;lt;/execution&amp;gt;&lt;br /&gt;    &amp;lt;/executions&amp;gt;&lt;br /&gt;    &amp;lt;configuration&amp;gt;&lt;br /&gt;        &amp;lt;format&amp;gt;{0,date,yyyy-MM-dd HH:mm}&amp;lt;/format&amp;gt;&lt;br /&gt;        &amp;lt;items&amp;gt;&lt;br /&gt;            &amp;lt;item&amp;gt;timestamp&amp;lt;/item&amp;gt;&lt;br /&gt;        &amp;lt;/items&amp;gt;&lt;br /&gt;    &amp;lt;/configuration&amp;gt;&lt;br /&gt;&amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;/pre&gt;Let's start now. Property file under &lt;span style="color: orange;"&gt;src/main/resources&lt;/span&gt; is called now &lt;span style="color: orange;"&gt;pe-showcase.properties&lt;/span&gt; and has again only one line (surprise).&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;nbsp;&lt;br /&gt;application.properties=${project.properties}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;This line gets resolved at build time as follows:&lt;br /&gt;&lt;pre class="brush:xml"&gt;application.properties={pe.jsf.impl=mojarra, pe.jsf.group=com.sun.faces, timestamp=1329486964505, svn.committedRevision=928, svn.revision=928, primefaces.theme.version=1.0.3, pe.impl.version=0.3.0-SNAPSHOT, pe.jsf.displayname=Mojarra, jetty.server.version=8.1.0.RC2, svn.committedDate=2012-02-17 01:48:44 +0100 (Fri, 17 Feb 2012), pe.jsf.version=2.1.6, primefaces.core.version=3.1.1, ...}&lt;br /&gt;&lt;/pre&gt;The task is now to parse this resolved line in a Java application. A good entry point for parsing in JSF is an application scoped bean noted with &lt;span style="color: orange;"&gt;eager=true&lt;/span&gt;.&lt;br /&gt;&lt;pre class="brush:java"&gt;@ApplicationScoped&lt;br /&gt;@ManagedBean(eager = true)&lt;br /&gt;public class TechnicalInfo {&lt;br /&gt;&lt;br /&gt;    private static final Logger LOGGER = Logger.getLogger(TechnicalInfo.class.getName());&lt;br /&gt;&lt;br /&gt;    private String primeFaces;&lt;br /&gt;    private String primeFacesExt;&lt;br /&gt;    private String jsfImpl;&lt;br /&gt;    private String server;&lt;br /&gt;    private String revision;&lt;br /&gt;    private String buildTime;&lt;br /&gt;    private boolean online = false;&lt;br /&gt;    private boolean mojarra = true;&lt;br /&gt;&lt;br /&gt;    @PostConstruct&lt;br /&gt;    protected void initialize() {&lt;br /&gt;        ResourceBundle rb;&lt;br /&gt;        try {&lt;br /&gt;            rb = ResourceBundle.getBundle("pe-showcase");&lt;br /&gt;&lt;br /&gt;            String strAppProps = rb.getString("application.properties");&lt;br /&gt;            int lastBrace = strAppProps.indexOf("}");&lt;br /&gt;            strAppProps = strAppProps.substring(1, lastBrace);&lt;br /&gt;&lt;br /&gt;            Map&amp;lt;String, String&amp;gt; appProperties = new HashMap&amp;lt;String, String&amp;gt;();&lt;br /&gt;            String[] appProps = strAppProps.split("[\\s,]+");&lt;br /&gt;            for (String appProp : appProps) {&lt;br /&gt;                String[] keyValue = appProp.split("=");&lt;br /&gt;                if (keyValue != null &amp;amp;&amp;amp; keyValue.length &amp;gt; 1) {&lt;br /&gt;                    appProperties.put(keyValue[0], keyValue[1]);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            primeFaces = "PrimeFaces: " + appProperties.get("primefaces.core.version");&lt;br /&gt;            primeFacesExt = "PrimeFaces Extensions: " + appProperties.get("pe.impl.version");&lt;br /&gt;            jsfImpl = "JSF-Impl.: " + appProperties.get("pe.jsf.displayname") + " " + appProperties.get("pe.jsf.version");&lt;br /&gt;            server = "Server: Jetty " + appProperties.get("jetty.server.version");&lt;br /&gt;            revision = "SVN-Revision: " + appProperties.get("svn.revision");&lt;br /&gt;&lt;br /&gt;            DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");&lt;br /&gt;            Calendar calendar = Calendar.getInstance();&lt;br /&gt;            calendar.setTimeInMillis(Long.valueOf(appProperties.get("timestamp")));&lt;br /&gt;            buildTime = "Build time: " + formatter.format(calendar.getTime());&lt;br /&gt;&lt;br /&gt;            online = Boolean.valueOf(appProperties.get("pe.webapp.online"));&lt;br /&gt;            mojarra = appProperties.get("pe.jsf.impl").contains("mojarra");&lt;br /&gt;        } catch (MissingResourceException e) {&lt;br /&gt;            LOGGER.warning("Resource bundle 'pe-showcase' was not found");&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    ... getter ...&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Access in JSF facelets:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;h:panelGrid columns="7" style="float: left;"&amp;gt;&lt;br /&gt;    &amp;lt;h:panelGroup styleClass="ui-icon ui-icon-info"/&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText value="#{technicalInfo.primeFaces},"/&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText value="#{technicalInfo.primeFacesExt},"/&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText value="#{technicalInfo.jsfImpl},"/&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText value="#{technicalInfo.server},"/&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText value="#{technicalInfo.revision},"/&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText value="#{technicalInfo.buildTime}"/&amp;gt;&lt;br /&gt;&amp;lt;/h:panelGrid&amp;gt;&lt;br /&gt;&lt;/pre&gt;And voilà. We have done this! Click on image to enlarge it.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-hC4LwggloA4/Tz5zIDU2CFI/AAAAAAAAAIQ/yMYY2FIqYFE/s1600/footer.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="27" src="http://2.bp.blogspot.com/-hC4LwggloA4/Tz5zIDU2CFI/AAAAAAAAAIQ/yMYY2FIqYFE/s640/footer.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-6465814942766294817?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/6465814942766294817/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2012/02/advanced-injection-of-maven-properties.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/6465814942766294817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/6465814942766294817'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2012/02/advanced-injection-of-maven-properties.html' title='Advanced injection of Maven properties into Java application'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-hC4LwggloA4/Tz5zIDU2CFI/AAAAAAAAAIQ/yMYY2FIqYFE/s72-c/footer.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-2909522325423251034</id><published>2012-02-15T07:23:00.000-08:00</published><updated>2012-02-15T07:23:49.403-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Inject Maven project informations into Java application</title><content type='html'>Do you have a Maven project and would like to inject project informations from&lt;span style="color: orange;"&gt; pom.xml&lt;/span&gt; into your application to avoid duplications? This is possible with resource filtering. This small guide will help you to achieve that. More funny advanced examples are coming soon in the next post. I have applied this approach for &lt;a href="http://code.google.com/p/primefaces-extensions/"&gt;PrimeFaces Extensions project&lt;/a&gt;, so that all examples are related to this project.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Step 1.&lt;/u&gt; Create a property file under &lt;span style="color: orange;"&gt;src/main/resources&lt;/span&gt;. In my case it's called &lt;span style="color: orange;"&gt;primefaces-extensions.properties&lt;/span&gt; and consists of only one line.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;nbsp;&lt;br /&gt;application.version=${project.version}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;Placeholder &lt;span style="color: orange;"&gt;${...}&lt;/span&gt; gets resolved at project build time. Maven also exposes other project properties like &lt;span style="color: orange;"&gt;${project.artifactId}&lt;/span&gt;, &lt;span style="color: orange;"&gt;${project.name}&lt;/span&gt;, etc. Please refer &lt;a href="http://docs.codehaus.org/display/MAVENUSER/MavenPropertiesGuide"&gt;Maven properties guide&lt;/a&gt;. Not only Maven self exposes such properties. Various Maven plugins as &lt;a href="http://mojo.codehaus.org/buildnumber-maven-plugin/"&gt;buildnumber-maven-plugin&lt;/a&gt; and &lt;a href="http://code.google.com/p/maven-svn-revision-number-plugin/"&gt;maven-svn-revision-number-plugin&lt;/a&gt; expose useful properties too.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Step 2.&lt;/u&gt; To get placeholders replaced you need to enable filtering in your &lt;span style="color: orange;"&gt;pom.xml&lt;/span&gt;.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;build&amp;gt;&lt;br /&gt;    &amp;lt;resources&amp;gt;&lt;br /&gt;        &amp;lt;resource&amp;gt;src/main/resources&amp;lt;/resource&amp;gt;&lt;br /&gt;        &amp;lt;filtering&amp;gt;true&amp;lt;/filtering&amp;gt;&lt;br /&gt;    &amp;lt;/resources&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;&amp;lt;/build&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;u&gt;Step 3.&lt;/u&gt; Access in Java is simple. I have created a singleton class &lt;span style="color: orange;"&gt;VersionProvider &lt;/span&gt;for that (because I only have one placeholder for project version). Project version is cached after the first access.&lt;br /&gt;&lt;pre class="brush:java"&gt;public final class VersionProvider {&lt;br /&gt;&lt;br /&gt;    private static final Logger LOGGER = Logger.getLogger(VersionProvider.class.getName());&lt;br /&gt;&lt;br /&gt;    private static final VersionProvider INSTANCE = new VersionProvider();&lt;br /&gt;    private String version;&lt;br /&gt;&lt;br /&gt;    private VersionProvider() {&lt;br /&gt;        ResourceBundle rb;&lt;br /&gt;        try {&lt;br /&gt;            rb = ResourceBundle.getBundle("primefaces-extensions");&lt;br /&gt;            version = rb.getString("application.version");&lt;br /&gt;        } catch (MissingResourceException e) {&lt;br /&gt;            LOGGER.warning("Resource bundle 'primefaces-extensions' was not found or error while reading current version.");&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static String getVersion() {&lt;br /&gt;        return INSTANCE.version;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;u&gt;Step 4.&lt;/u&gt; Using in any places is simple as well. Just call &lt;span style="color: orange;"&gt;VersionProvider.getVersion()&lt;/span&gt;. For instance in the following JSF listener class&lt;br /&gt;&lt;pre class="brush:java"&gt;public class PostConstructApplicationEventListener implements SystemEventListener {&lt;br /&gt;&lt;br /&gt;    private static final Logger LOGGER = Logger.getLogger(PostConstructApplicationEventListener.class.getName());&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public boolean isListenerForSource(final Object source) {&lt;br /&gt;        return true;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public void processEvent(final SystemEvent event) {&lt;br /&gt;        if (StringUtils.isNotBlank(VersionProvider.getVersion())) {&lt;br /&gt;            LOGGER.log(Level.INFO, "Running on PrimeFaces Extensions {0}", VersionProvider.getVersion());&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;or in JSF resource handler&lt;br /&gt;&lt;pre class="brush:java"&gt;public class PrimeFacesExtensionsResource extends ResourceWrapper {&lt;br /&gt;&lt;br /&gt;    private Resource wrapped;&lt;br /&gt;    private String version;&lt;br /&gt;&lt;br /&gt;    public PrimeFacesExtensionsResource(final Resource resource) {&lt;br /&gt;        super();&lt;br /&gt;        wrapped = resource;&lt;br /&gt;&lt;br /&gt;        // get current version&lt;br /&gt;        if (StringUtils.isNotBlank(VersionProvider.getVersion())) {&lt;br /&gt;            version = "&amp;amp;v=" + VersionProvider.getVersion();&lt;br /&gt;        } else {&lt;br /&gt;            version = UUID.randomUUID().toString();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public String getRequestPath() {&lt;br /&gt;        return super.getRequestPath() + version;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;With resource filtering you don't need to care about available current project infos in Java programs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-2909522325423251034?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/2909522325423251034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2012/02/inject-maven-project-informations-into.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2909522325423251034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2909522325423251034'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2012/02/inject-maven-project-informations-into.html' title='Inject Maven project informations into Java application'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-6801679006387859079</id><published>2012-01-31T08:57:00.000-08:00</published><updated>2012-02-05T06:03:52.787-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Cron Job to restart Jetty Server</title><content type='html'>If you have an Java hosting on a virtual server, you normally have limited resources for that. That means you only have a certain amount of RAM. This leads to memory problems when deploying large applications. Restart the server by hand is annoying. Fortunately there are cron jobs. A cron job is a task in Linux which is to be executed at specific times automatically. The simplest way to start a cron job in Linux is to place a shell script below one of the following folders:&lt;br /&gt;/etc/cron.daily&lt;br /&gt;/etc/cron.weekly&lt;br /&gt;/etc/cron.monthly&lt;br /&gt;&lt;br /&gt;I intend to show a shell script for Jetty 8 server which is installed in &lt;span style="color: orange;"&gt;/opt/jetty-distribution-8.1.0.RC2/&lt;/span&gt; (path on my virtual server). The script checks the process id of the running Jetty server, kills it if it was found and restarts the server with the command "&lt;span style="color: orange;"&gt;nohup java -jar start.jar&lt;/span&gt;".&lt;br /&gt;&lt;pre class="brush:xml"&gt;#! /bin/sh&lt;br /&gt;&lt;br /&gt;jettyPid='pgrep -f "java -jar start.jar"'&lt;br /&gt;&lt;br /&gt;if [ "$jettyPid" != "" ]&lt;br /&gt;then&lt;br /&gt;kill -9 $jettyPid&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;jettyHome="/opt/jetty-distribution-8.1.0.RC2/"&lt;br /&gt;cd $jettyHome&lt;br /&gt;nohup java -jar start.jar&lt;br /&gt;&lt;br /&gt;exit&lt;br /&gt;&lt;/pre&gt;Alternative shorter variant:&lt;br /&gt;&lt;pre class="brush:xml"&gt;#! /bin/sh&lt;br /&gt;&lt;br /&gt;pgrep -f "java -jar start.jar" | xargs -i kill {}&lt;br /&gt;&lt;br /&gt;cd /opt/jetty-distribution-8.1.0.RC2/&lt;br /&gt;nohup java -jar start.jar&lt;br /&gt;&lt;br /&gt;exit&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-6801679006387859079?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/6801679006387859079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2012/01/cron-job-to-restart-jetty-server.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/6801679006387859079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/6801679006387859079'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2012/01/cron-job-to-restart-jetty-server.html' title='Cron Job to restart Jetty Server'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-9190358857051254281</id><published>2012-01-01T14:48:00.000-08:00</published><updated>2012-01-01T14:48:58.451-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><category scheme='http://www.blogger.com/atom/ns#' term='PrimeFaces Extensions'/><title type='text'>New release of web resource optimization plugin</title><content type='html'>I have released a new 0.3 version of the &lt;a href="http://code.google.com/p/primefaces-extensions/wiki/GettingStartedClosureCompiler"&gt;Maven plugin for web resource optimization&lt;/a&gt;. As I mentioned in the last posts this plugin was created as a part of the PrimeFaces Extensions project. It produces better compression results than YUI Compressor and has some nice features. The current release fixes only one issue. &lt;a href="http://code.google.com/p/primefaces-extensions/wiki/ReleaseNotes"&gt;Release notes are here&lt;/a&gt;. The plugin is available in the Maven central repository.&lt;br /&gt;&lt;br /&gt;If you have any questions regarding to the configuration, ask me please in the &lt;a href="http://groups.google.com/group/primefaces-extensions"&gt;PrimeFaces Extensions forum&lt;/a&gt;. This forum is also a good place for all questions to the components and more. Unfortunately, but PrimeFaces lead doesn't like to see any discussions related to our extensions in the main PrimeFaces forum. He considers such topics as advertisement and locks / removes them. That hurts and is weird because if it would be an advertisement, it would be an advertisement for PrimeFaces. We have "PrimeFaces" in the name "PrimeFaces Extensions". The aim was never to do an advertisement or get money. This project is just for fun, everybody can participate in.&lt;br /&gt;&lt;br /&gt;Currently we are working on the last use cases for our showcase and plan to do a release in the middle of January. Next releases will be published at frequent intervals and include less stuff - approximately 2-4 new components, client behaviors, converters or similar JSF 2 related artefacts. Some stuff is amazing, so stay tuned.&lt;br /&gt;&lt;br /&gt;Best wishes for the New Year!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-9190358857051254281?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/9190358857051254281/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2012/01/new-release-of-web-resource.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/9190358857051254281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/9190358857051254281'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2012/01/new-release-of-web-resource.html' title='New release of web resource optimization plugin'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-351587743240680995</id><published>2011-12-30T02:53:00.000-08:00</published><updated>2011-12-30T04:58:15.219-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>Efficient component tree traversal in JSF</title><content type='html'>Everybody knows about &lt;a href="http://javaserverfaces.java.net/nonav/docs/2.1/javadocs/javax/faces/component/UIComponent.html#findComponent%28java.lang.String%29"&gt;findComponent()&lt;/a&gt; and &lt;a href="http://javaserverfaces.java.net/nonav/docs/2.1/javadocs/javax/faces/component/UIComponent.html#invokeOnComponent%28javax.faces.context.FacesContext,%20java.lang.String,%20javax.faces.component.ContextCallback%29"&gt;invokeOnComponent()&lt;/a&gt; methods in JSF to find a component and doing something with it. The first method expects a special search expression and the second one component's clientId. They belong to &lt;span style="color: orange;"&gt;UIComponent&lt;/span&gt; class, so that any &lt;span style="color: orange;"&gt;UIComponent&lt;/span&gt; can acts as a start point in the view hierarchy. But what is about if we want to find many components at some start point in the view hierarchy which match certain conditions? We can apply &lt;a href="http://javaserverfaces.java.net/nonav/docs/2.1/javadocs/javax/faces/component/UIComponent.html#getChildren%28%29"&gt;getChildren()&lt;/a&gt; rekursive, but we wish us a convenient method for tree traversal. Tree traversal refers to the process of visiting each node in a component tree data structure. There is an efficient method in JSF accomplishing this task - &lt;a href="http://javaserverfaces.java.net/nonav/docs/2.1/javadocs/javax/faces/component/UIComponent.html#visitTree%28javax.faces.component.visit.VisitContext,%20javax.faces.component.visit.VisitCallback%29"&gt;visitTree()&lt;/a&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;public boolean visitTree(VisitContext context, VisitCallback callback)&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: orange;"&gt;context &lt;/span&gt;is an instance of &lt;span style="color: orange;"&gt;VisitContext&lt;/span&gt; class that is used to hold state relating to performing a component tree visit. &lt;span style="color: orange;"&gt;callback &lt;/span&gt;is an instance of &lt;span style="color: orange;"&gt;VisitCallback&lt;/span&gt; whose visit method will be called for each node visited. Let's start with a practical example. Our task is to find and gather all components implementing &lt;span style="color: orange;"&gt;EditableValueHolder&lt;/span&gt;. Such components implement &lt;span style="color: orange;"&gt;resetValue()&lt;/span&gt; method which allows to reset component's submitted, locale values, etc. to an un-initialized state. Furthermore, another requirement is to skip sub-tree traversal for a component which should be not rendered (don't visit sub-components). In other words we want to find only editable components to be rendered. Assume, the start component calls &lt;span style="color: orange;"&gt;target&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;UIComponent target = ...&lt;br /&gt;&lt;/pre&gt;It can be got in an action / event listener by &lt;span style="color: orange;"&gt;event.getComponent()&lt;/span&gt; or somewhere else by &lt;span style="color: orange;"&gt;findComponent()&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;We are ready now to create a special &lt;span style="color: orange;"&gt;EditableValueHoldersVisitCallback&lt;/span&gt; in order to find all mentioned above sub-components and call &lt;span style="color: orange;"&gt;visitTree &lt;/span&gt;on the &lt;span style="color: orange;"&gt;target &lt;/span&gt;component with this callback. &lt;span style="color: orange;"&gt;EditableValueHoldersVisitCallback &lt;/span&gt;gathers sub-components we want to reset.&lt;br /&gt;&lt;pre class="brush:java"&gt;EditableValueHoldersVisitCallback visitCallback = new EditableValueHoldersVisitCallback();&lt;br /&gt;target.visitTree(VisitContext.createVisitContext(FacesContext.getCurrentInstance()), visitCallback);&lt;br /&gt;&lt;br /&gt;// iterate over found sub-components and reset their values&lt;br /&gt;List&amp;lt;EditableValueHolder&amp;gt; editableValueHolders = visitCallback.getEditableValueHolders();&lt;br /&gt;for (EditableValueHolder editableValueHolder : editableValueHolders) {&lt;br /&gt;    editableValueHolder.resetValue();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Callback looks like this one&lt;br /&gt;&lt;pre class="brush:java"&gt;public class EditableValueHoldersVisitCallback implements VisitCallback {&lt;br /&gt;&lt;br /&gt;    private List&amp;lt;EditableValueHolder&amp;gt; editableValueHolders = new ArrayList&amp;lt;EditableValueHolder&amp;gt;();&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public VisitResult visit(final VisitContext context, final UIComponent target) {&lt;br /&gt;        if (!target.isRendered()) {&lt;br /&gt;            return VisitResult.REJECT;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        if (target instanceof EditableValueHolder) {&lt;br /&gt;            editableValueHolders.add((EditableValueHolder) target);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return VisitResult.ACCEPT;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public List&amp;lt;EditableValueHolder&amp;gt; getEditableValueHolders() {&lt;br /&gt;        return editableValueHolders;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Result &lt;span style="color: orange;"&gt;VisitResult.REJECT&lt;/span&gt; indicates that the tree visit should be continued, but should skip the current component's subtree (remember our requirement?). &lt;span style="color: orange;"&gt;VisitResult.ACCEPT&lt;/span&gt; indicates that the tree visit should descend into current component's subtree. There is also &lt;span style="color: orange;"&gt;VisitResult.COMPLETE&lt;/span&gt; as return value if the tree visit should be terminated.&lt;br /&gt;&lt;br /&gt;Some components extending &lt;span style="color: orange;"&gt;UINamingContainer &lt;/span&gt;override the behavior of &lt;span style="color: orange;"&gt;visitTree()&lt;/span&gt;. For instance, &lt;span style="color: orange;"&gt;UIData &lt;/span&gt;overrides this method to handle iteration correctly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-351587743240680995?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/351587743240680995/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/12/efficient-component-tree-traversal-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/351587743240680995'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/351587743240680995'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/12/efficient-component-tree-traversal-in.html' title='Efficient component tree traversal in JSF'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-3350261414632675830</id><published>2011-12-27T05:08:00.000-08:00</published><updated>2011-12-27T05:15:03.429-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Maven plugin for web resource optimization - advanced settings</title><content type='html'>In the &lt;a href="http://ovaraksin.blogspot.com/2011/12/new-maven-plugin-for-web-resource.html"&gt;last post&lt;/a&gt; I have introduced a new Maven plugin &lt;a href="http://code.google.com/p/primefaces-extensions/wiki/GettingStartedClosureCompiler"&gt;resources-optimizer-maven-plugin&lt;/a&gt;. This post is about two advanced features. &lt;span style="color: orange;"&gt;Aggregation&lt;/span&gt; tag has a sub-tag &lt;span style="color: orange;"&gt;subDirMode&lt;/span&gt;. This is an aggregation per sub-folder. Assume, JavaScript / CSS files are grouped by sub-folders which represent software modules. Resources of each module can be optimized separately in an easy way. As output we would have aggregated files per sub-folder. Names of aggregated files are the same as their folder names where they are placed. Files are aggregated in the lexicographic order. The following pictures demonstrate this approach.&lt;br /&gt;&lt;br /&gt;Original source files below sub-folder &lt;span style="color: orange;"&gt;keyfilter&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-joJk2Fko62Y/Tvm-lp1jzKI/AAAAAAAAAHk/-OmtUWhr10E/s1600/originalFiles.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-joJk2Fko62Y/Tvm-lp1jzKI/AAAAAAAAAHk/-OmtUWhr10E/s1600/originalFiles.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Aggregated file in target below sub-folder &lt;span style="color: orange;"&gt;keyfilter&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-u47v1EHyyBs/Tvm-uQYZqXI/AAAAAAAAAHw/sHZYYpPVB1Q/s1600/aggregatedFiles.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-u47v1EHyyBs/Tvm-uQYZqXI/AAAAAAAAAHw/sHZYYpPVB1Q/s1600/aggregatedFiles.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;This can be achieved with the following resources set&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;resourcesSet&amp;gt;&lt;br /&gt;    &amp;lt;includes&amp;gt;&lt;br /&gt;        ...&lt;br /&gt;        &amp;lt;include&amp;gt;keyfilter/**&amp;lt;/include&amp;gt;&lt;br /&gt;        ...&lt;br /&gt;    &amp;lt;/includes&amp;gt;&lt;br /&gt;    &amp;lt;aggregations&amp;gt;&lt;br /&gt;        &amp;lt;aggregation&amp;gt;&lt;br /&gt;            &amp;lt;inputDir&amp;gt;...&amp;lt;/inputDir&amp;gt;&lt;br /&gt;            &amp;lt;subDirMode&amp;gt;true&amp;lt;/subDirMode&amp;gt;&lt;br /&gt;        &amp;lt;/aggregation&amp;gt;&lt;br /&gt;    &amp;lt;/aggregations&amp;gt;&lt;br /&gt;&amp;lt;/resourcesSet&amp;gt;&lt;br /&gt;&lt;/pre&gt;The second feature is a preparation of uncompressed resources. Sometimes you have to build / deliver compressed and uncompressed resources. In JSF you can use then uncompressed resources if ProjectStage is "&lt;span style="color: orange;"&gt;Development&lt;/span&gt;". RichFaces has e.g. this handy feature. &lt;span style="color: orange;"&gt;resources-optimizer-maven-plugin&lt;/span&gt; allows to define several aggregation tags, e.g. one for compressed and one for uncompressed resources. The following picture demonstrates this approach.&lt;br /&gt;&lt;br /&gt;Two folders, for compressed (&lt;span style="color: orange;"&gt;primefaces-extensions&lt;/span&gt;) and uncompressed (&lt;span style="color: orange;"&gt;primefaces-extensions-uncompressed&lt;/span&gt;) resources:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Y_Gx3LKwE9U/Tvm_aK0VuqI/AAAAAAAAAH8/7DD6AYfMpB0/s1600/uncompressedResFolder.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-Y_Gx3LKwE9U/Tvm_aK0VuqI/AAAAAAAAAH8/7DD6AYfMpB0/s1600/uncompressedResFolder.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;That can be achieved with this resources set&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;resourcesSet&amp;gt;&lt;br /&gt;    &amp;lt;includes&amp;gt;&lt;br /&gt;        ...&lt;br /&gt;    &amp;lt;/includes&amp;gt;&lt;br /&gt;    &amp;lt;aggregations&amp;gt;&lt;br /&gt;        &amp;lt;aggregation&amp;gt;&lt;br /&gt;            &amp;lt;inputDir&amp;gt;${resources.dir.compressed}&amp;lt;/inputDir&amp;gt;&lt;br /&gt;            ...&lt;br /&gt;        &amp;lt;/aggregation&amp;gt;&lt;br /&gt;        &amp;lt;aggregation&amp;gt;&lt;br /&gt;            &amp;lt;withoutCompress&amp;gt;true&amp;lt;/withoutCompress&amp;gt;&lt;br /&gt;            &amp;lt;inputDir&amp;gt;${resources.dir.uncompressed}&amp;lt;/inputDir&amp;gt;&lt;br /&gt;            ...&lt;br /&gt;        &amp;lt;/aggregation&amp;gt;&lt;br /&gt;    &amp;lt;/aggregations&amp;gt;&lt;br /&gt;&amp;lt;/resourcesSet&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;properties&amp;gt;&lt;br /&gt;    &amp;lt;resources.dir.compressed&amp;gt;&lt;br /&gt;        ${project.build.directory}/classes/META-INF/resources/primefaces-extensions&lt;br /&gt;    &amp;lt;/resources.dir.compressed&amp;gt;&lt;br /&gt;    &amp;lt;resources.dir.uncompressed&amp;gt;&lt;br /&gt;        ${project.build.directory}/classes/META-INF/resources/primefaces-extensions-uncompressed&lt;br /&gt;    &amp;lt;/resources.dir.uncompressed&amp;gt;&lt;br /&gt;&amp;lt;/properties&amp;gt;&lt;br /&gt;&lt;/pre&gt;Output directory for uncompressed resources should be created first. Put &lt;span style="color: orange;"&gt;maven-resources-plugin&lt;/span&gt; with phase &lt;span style="color: orange;"&gt;generate-resources&lt;/span&gt; in front of &lt;span style="color: orange;"&gt;resources-optimizer-maven-plugin&lt;/span&gt; (phase &lt;span style="color: orange;"&gt;prepare-package&lt;/span&gt;).&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;plugin&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;maven-resources-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;executions&amp;gt;&lt;br /&gt;        &amp;lt;execution&amp;gt;&lt;br /&gt;            &amp;lt;id&amp;gt;copy-resources&amp;lt;/id&amp;gt;&lt;br /&gt;            &amp;lt;phase&amp;gt;generate-resources&amp;lt;/phase&amp;gt;&lt;br /&gt;            &amp;lt;goals&amp;gt;&lt;br /&gt;                &amp;lt;goal&amp;gt;copy-resources&amp;lt;/goal&amp;gt;&lt;br /&gt;            &amp;lt;/goals&amp;gt;&lt;br /&gt;            &amp;lt;configuration&amp;gt;&lt;br /&gt;                &amp;lt;outputDirectory&amp;gt;${resources.dir.uncompressed}&amp;lt;/outputDirectory&amp;gt;&lt;br /&gt;                &amp;lt;resources&amp;gt;&lt;br /&gt;                    &amp;lt;resource&amp;gt;&lt;br /&gt;                        &amp;lt;directory&amp;gt;${project.basedir}/src/main/resources/META-INF/resources/primefaces-extensions&amp;lt;/directory&amp;gt;&lt;br /&gt;                    &amp;lt;/resource&amp;gt;&lt;br /&gt;                &amp;lt;/resources&amp;gt;&lt;br /&gt;            &amp;lt;/configuration&amp;gt;&lt;br /&gt;        &amp;lt;/execution&amp;gt;&lt;br /&gt;    &amp;lt;/executions&amp;gt;&lt;br /&gt;&amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;/pre&gt;These were examples for an JAR project. The same is also valid for WAR (web) projects of course.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-3350261414632675830?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/3350261414632675830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/12/maven-plugin-for-web-resource.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/3350261414632675830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/3350261414632675830'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/12/maven-plugin-for-web-resource.html' title='Maven plugin for web resource optimization - advanced settings'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-joJk2Fko62Y/Tvm-lp1jzKI/AAAAAAAAAHk/-OmtUWhr10E/s72-c/originalFiles.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-1918072523053814397</id><published>2011-12-19T11:17:00.000-08:00</published><updated>2011-12-20T01:43:51.100-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><category scheme='http://www.blogger.com/atom/ns#' term='PrimeFaces Extensions'/><title type='text'>New Maven plugin for web resource optimization</title><content type='html'>Two months ago I released the first version of a new &lt;a href="http://code.google.com/p/primefaces-extensions/wiki/GettingStartedClosureCompiler"&gt;Maven plugin for web resource optimization&lt;/a&gt;. This plugin was created as a part of the &lt;a href="http://code.google.com/p/primefaces-extensions/"&gt;PrimeFaces Extensions project&lt;/a&gt;. What is the PrimeFaces Extensions project? Thomas Andraschko and me have launched this young project with the aim of extending JSF library &lt;a href="http://www.primefaces.org/"&gt;PrimeFaces&lt;/a&gt;. What does extending mean? We don't have "extends SomePrimeFacesComponent" in the code. It doesn't make sense to copy-&amp;amp;-paste or overwrite existing PrimeFaces code. PrimeFaces is a rapidly evolving component set and costs to maintain the entire code from release to release would be too high. Extending means, we use core functionality of PrimeFaces like &lt;span style="color: orange;"&gt;core.js&lt;/span&gt; and &lt;span style="color: orange;"&gt;CoreRenderer.java&lt;/span&gt;. Well. What for components and other stuff we have is not the topic of this post. This is a topic for next post(s). I just would like to appeal to everybody having JSF / PrimeFaces expert knowledge to contact us. Any help would be appreciated. We have great ideas and plans, but Thomas and me are full time worker and involving in various daily projects, so that time for PrimeFaces Extensions is very sparse. Even worse in my case. I can only work 15-20% for JSF in my daily work currently. So, everybody with experience in JSF / PrimeFaces can join this open source project.&lt;br /&gt;&lt;br /&gt;Maven plugin for resource optimization can compress and merge JavaScript and CSS files very efficiently. It produces better results than all plugins I know. The new Maven plugin combines &lt;a href="http://code.google.com/intl/en/closure/compiler/"&gt;Google Closure Compiler&lt;/a&gt; (for JavaScript files) and &lt;a href="http://developer.yahoo.com/yui/compressor/"&gt;YUI Compressor&lt;/a&gt; (for CSS files). The new plugin is highly configurable and allows some nice features which don't exist in other plugins. I would like to mention some highlights:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Flexible resource sets describing resources to be processed.&lt;/li&gt;&lt;li&gt;Settings for compilation and warning levels for Google Closure Compiler. Defaults are &lt;span style="color: orange;"&gt;SIMPLE_OPTIMIZATIONS&lt;/span&gt; and &lt;span style="color: orange;"&gt;QUIET&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Aggregation with or without compression.&lt;/li&gt;&lt;li&gt;Suffix for compressed / aggregated files if needed.&lt;/li&gt;&lt;li&gt;&lt;span style="color: orange;"&gt;SubDirMode&lt;/span&gt; for files aggregation. Resources of each software module can be optimized separately in an easy way. It makes sense e.g. for component / widget development because you can say "merge files for component A to one big file and don't merge files for component B".&lt;/li&gt;&lt;li&gt;Possiblity to define a file to be prepended to the aggregated file.&lt;/li&gt;&lt;li&gt;Possiblity to build compressed and uncompressed resources at the same time. PrimeFaces community already asked about uncompressed resources for development stage. RichFaces and some other libs can deliver uncompressed resources if the ProjectStage is "&lt;span style="color: orange;"&gt;Development&lt;/span&gt;". We have also done this for PrimeFaces Extensions by means of this plugin. A special JSF ResourceHandler can stream down uncompressed resources to the browser for the ProjectStage "Development". Never crypto-messages like "&lt;span style="color: orange;"&gt;e is undefined&lt;/span&gt;" anymore!&lt;/li&gt;&lt;/ul&gt;I have tried to write a more or less &lt;a href="http://code.google.com/p/primefaces-extensions/wiki/GettingStartedClosureCompiler"&gt;comprehensive documentaion&lt;/a&gt;. Simple check it! We already use this plugin with success in 6-8 JAR and WAR projects. I have also drawn a comparison diagram for PrimeFaces: size in bytes without compression, with &lt;span style="color: orange;"&gt;yuicompressor-maven-plugin&lt;/span&gt; and with our &lt;span style="color: orange;"&gt;resources-optimizer-maven-plugin&lt;/span&gt;. And I have prepared a configuration for PrimeFaces to make changes easy. More details in the online documentation. We would be glad to see the &lt;span style="color: orange;"&gt;resources-optimizer-maven-plugin&lt;/span&gt; in PrimeFaces! It's worth. This plugin is available in the Maven central repository. In the meantime I have released a &lt;a href="http://search.maven.org/#search%7Cga%7C1%7Cresources-optimizer-maven-plugin"&gt;new 0.2 version&lt;/a&gt;. Feedback is welcome. Thanks.&lt;br /&gt;&lt;br /&gt;The next Maven plugin I'm planning to write is a CDK (component development kit) for PrimeFaces components (low prio, depends on free time). PrimeFaces has already one, but only for internal use. Futhermore, PrimeFaces's plugin doesn't generate component's source files under source folder (they are not under version control) and has an expensive configuration. The new CDK will be configurable via name conventions and avoid expensive configuration. The technique for that will be &lt;span style="color: orange;"&gt;Java Emitter Templates&lt;/span&gt; (JET) from Eclipse Modeling Framework. Here is again - every help is appreciated. We have some code styles, so that our code is clean and optimized. But it's not a problem at all to follow them, even in a remote team. I'm convinced, the work in a distributed team can be very efficient.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-1918072523053814397?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/1918072523053814397/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/12/new-maven-plugin-for-web-resource.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1918072523053814397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1918072523053814397'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/12/new-maven-plugin-for-web-resource.html' title='New Maven plugin for web resource optimization'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-685398738655073373</id><published>2011-12-16T07:01:00.000-08:00</published><updated>2011-12-16T07:17:46.181-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Test'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Install Windows VHDs on Linux for testing websites with Internet Explorer</title><content type='html'>Need to test websites in multiple Internet Explorer versions under Linux / Mac OSX? No problem. Microsoft created free &lt;a href="http://www.microsoft.com/download/en/details.aspx?id=11575"&gt;Windows Virtual PC VHDs&lt;/a&gt; with the purpose of allowing web designers to test websites in Internet Explorer 7-9. There is a &lt;a href="https://github.com/xdissent/ievms"&gt;script ievms&lt;/a&gt; simplifying the installation. But before you have to install the latest &lt;a href="https://www.virtualbox.org/"&gt;VirtualBox&lt;/a&gt;. You can do this e.g. via Package Manager (Ubuntu), Yast (OpenSuse) or via Linux terminal&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;nbsp;&lt;br /&gt;sudo apt-get install virtualbox-4.1&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;The next step is the installation of &lt;span style="color: orange;"&gt;VirtualBox Extension Pack&lt;/span&gt;. This is necessary for USB 2.0 devices, shared folders, better screen resolution, etc. The best way is to download and install the package for the &lt;span style="color: orange;"&gt;VirtualBox Extension Pack&lt;/span&gt; manually.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;nbsp;&lt;br /&gt;wget http://download.virtualbox.org/virtualbox/4.1.6/Oracle_VM_VirtualBox_Extension_Pack-4.1.6-74713.vbox-extpack&lt;br /&gt;VBoxManage extpack install Oracle_VM_VirtualBox_Extension_Pack-4.1.6-74713.vbox-extpack&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;Open &lt;span style="color: orange;"&gt;VirtialBox&lt;/span&gt; tnen and go to File &amp;gt; Preferences &amp;gt; Extensions tab. Click there the "add" button and browse to the &lt;span style="color: orange;"&gt;VirtualBox Extension Pack&lt;/span&gt;. Now you need to install &lt;span style="color: orange;"&gt;curl&lt;/span&gt; (tool to transfer data from or to a server) and &lt;span style="color: orange;"&gt;unrar&lt;/span&gt; (command-line applications for extracting RAR archives). In Ubuntu, install them using the command below.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;nbsp;&lt;br /&gt;sudo apt-get install curl unrar&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;To download and run the mentioned above script, use the following command in a terminal.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;nbsp;&lt;br /&gt;curl -s https://raw.github.com/xdissent/ievms/master/ievms.sh | bash&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;The above command will download Windows VHDs for IE7, IE8 and IE9. If you only need one specific Internet Explorer version, e.g. IE9, you can run:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;nbsp;&lt;br /&gt;curl -s https://raw.github.com/xdissent/ievms/master/ievms.sh | IEVMS_VERSIONS="9" bash&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;At this point, the download will start and it will take a while. The VHD archives are massive and can take hours to download. Each version is installed into a subdirectory of &lt;span style="color: orange;"&gt;~/.ievms/vhd/&lt;/span&gt;. At the end you can delete the downloaded archives (&lt;span style="color: orange;"&gt;*.exe&lt;/span&gt; and &lt;span style="color: orange;"&gt;*.rar&lt;/span&gt; files) below this folder if you want to free up some space. You are ready to test websites in IE7-IE9 now. The password for all VMs is "&lt;span style="color: orange;"&gt;Password1&lt;/span&gt;". The picture below shows a &lt;span style="color: orange;"&gt;VirtualBox&lt;/span&gt; with IE9.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-9XOqQB970mo/TutcRdOeg1I/AAAAAAAAAHQ/ucD6smAconQ/s1600/IE9VM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="475" src="http://2.bp.blogspot.com/-9XOqQB970mo/TutcRdOeg1I/AAAAAAAAAHQ/ucD6smAconQ/s640/IE9VM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The next picture shows that I set shared folders to exchange data between Windows 7 in VM and my Kubuntu 11.10 (Oneiric Ocelot).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Hac1iIdG6mM/TutcaLS6NDI/AAAAAAAAAHY/HU_Bgw9rfNM/s1600/SettingsVM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="476" src="http://1.bp.blogspot.com/-Hac1iIdG6mM/TutcaLS6NDI/AAAAAAAAAHY/HU_Bgw9rfNM/s640/SettingsVM.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;You can start your web application on Linux. But how to access a running web application on Windows (VirtualBox)? Linux has a command tool &lt;span style="color: orange;"&gt;ifconfig&lt;/span&gt; to configure, control and query TCP/IP network interface parameters. Open a terminal and type &lt;span style="color: orange;"&gt;ifconfig&lt;/span&gt;. Find an IP address you Linux mashine is accessible from. I have e.g. &lt;span style="color: orange;"&gt;192.168.254.21&lt;/span&gt; for &lt;span style="color: orange;"&gt;wlan0&lt;/span&gt; interface. You are able to call now&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;nbsp;&lt;br /&gt;http://192.168.254.21:8080/...&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;in Interner Exloper on Windows. The IP address is like a localhost for your web application running on Linix. Remaning part behind this address is the same on both OS.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-685398738655073373?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/685398738655073373/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/12/install-windows-vhds-on-linux-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/685398738655073373'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/685398738655073373'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/12/install-windows-vhds-on-linux-for.html' title='Install Windows VHDs on Linux for testing websites with Internet Explorer'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-9XOqQB970mo/TutcRdOeg1I/AAAAAAAAAHQ/ucD6smAconQ/s72-c/IE9VM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-1096589826212222922</id><published>2011-11-16T03:38:00.000-08:00</published><updated>2011-11-16T05:36:49.518-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>5 useful methods JSF developers should know</title><content type='html'>The aim of this post is a summary about some handy methods for JSF developers they can use in their day-to-day work. An utility class is a good place to put all methods together. I would call such class &lt;span style="color: orange;"&gt;FacesAccessor&lt;/span&gt;. The first method is probably the most used one. It returns managed bean by the given name. The bean must be registered either per &lt;span style="color: orange;"&gt;faces-config.xml&lt;/span&gt; or annotation. Injection is good, but sometimes if beans are rare called, it's not necessary to inject beans into each other.&lt;br /&gt;&lt;pre class="brush:java"&gt;public static Object getManagedBean(final String beanName) {&lt;br /&gt;    FacesContext fc = FacesContext.getCurrentInstance();&lt;br /&gt;    Object bean;&lt;br /&gt;    &lt;br /&gt;    try {&lt;br /&gt;        ELContext elContext = fc.getELContext();&lt;br /&gt;        bean = elContext.getELResolver().getValue(elContext, null, beanName);&lt;br /&gt;    } catch (RuntimeException e) {&lt;br /&gt;        throw new FacesException(e.getMessage(), e);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (bean == null) {&lt;br /&gt;        throw new FacesException("Managed bean with name '" + beanName&lt;br /&gt;            + "' was not found. Check your faces-config.xml or @ManagedBean annotation.");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return bean;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;u&gt;Using:&lt;/u&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;@ManagedBean&lt;br /&gt;public class PersonBean {&lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PersonBean personBean = (PersonBean)FacesAccessor.getManagedBean("personBean");&lt;br /&gt;&lt;br /&gt;// do something with personBean&lt;br /&gt;&lt;/pre&gt;The second method is useful for JSF component developers and everyone who would like to evaluate the given value expression &lt;span style="color: orange;"&gt;#{...}&lt;/span&gt; and sets the result to the given value.&lt;br /&gt;&lt;pre class="brush:java"&gt;public static void setValue2ValueExpression(final Object value, final String expression) {&lt;br /&gt;    FacesContext facesContext = FacesContext.getCurrentInstance();&lt;br /&gt;    ELContext elContext = facesContext.getELContext();&lt;br /&gt;&lt;br /&gt;    ValueExpression targetExpression = &lt;br /&gt;        facesContext.getApplication().getExpressionFactory().createValueExpression(elContext, expression, Object.class);&lt;br /&gt;    targetExpression.setValue(elContext, value);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;u&gt;Using:&lt;/u&gt;&lt;br /&gt;I personally use this method for the "log off functionality". After an user is logged off, he/she will see a special "logoff page". The "logoff page" uses user settings (e.g. theme, language, etc.) from a sesion scoped bean. But this session scoped bean doesn't exist more because the session was invalidated. What to do? Here is the code snippet from my logout method.&lt;br /&gt;&lt;pre class="brush:java"&gt;UserSettings userSettings = (UserSettings) FacesAccessor.getManagedBean("userSettings");&lt;br /&gt;&lt;br /&gt;// invalidate session&lt;br /&gt;ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();&lt;br /&gt;HttpSession session = (HttpSession) ec.getSession(false);&lt;br /&gt;session.invalidate();&lt;br /&gt;&lt;br /&gt;// create new session&lt;br /&gt;((HttpServletRequest) ec.getRequest()).getSession(true);&lt;br /&gt;&lt;br /&gt;// restore last used user settings because login / logout pages reference "userSettings"&lt;br /&gt;FacesAccessor.setValue2ValueExpression(userSettings, "#{userSettings}");&lt;br /&gt;&lt;br /&gt;// redirect to the specified logout page&lt;br /&gt;ec.redirect(ec.getRequestContextPath() + "/views/logout.jsf");&lt;br /&gt;&lt;/pre&gt;The third method maps a variable to the given value expression&lt;span style="color: orange;"&gt; #{...}&lt;/span&gt;. It uses &lt;span style="color: orange;"&gt;javax.el.VariableMapper&lt;/span&gt; to assign the expression to the specified variable, so that any reference to that variable will be replaced by the expression in EL evaluations.&lt;br /&gt;&lt;pre class="brush:java"&gt;public static void mapVariable2ValueExpression(final String variable, final String expression) {&lt;br /&gt;    FacesContext facesContext = FacesContext.getCurrentInstance();&lt;br /&gt;    ELContext elContext = facesContext.getELContext();&lt;br /&gt;    &lt;br /&gt;    ValueExpression targetExpression =&lt;br /&gt;        facesContext.getApplication().getExpressionFactory().createValueExpression(elContext, expression, Object.class);&lt;br /&gt;    elContext.getVariableMapper().setVariable(variable, targetExpression);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;u&gt;Using:&lt;/u&gt;&lt;br /&gt;Assume, "&lt;span style="color: orange;"&gt;PersonBean&lt;/span&gt;" is a managed bean having "&lt;span style="color: orange;"&gt;name&lt;/span&gt;" attribute and "&lt;span style="color: orange;"&gt;PersonsBean&lt;/span&gt;" is a bean holding many instances of "&lt;span style="color: orange;"&gt;PersonBean&lt;/span&gt;" (as array, collection or map). The following code allows to use "&lt;span style="color: orange;"&gt;personBean&lt;/span&gt;" as a reference to a specific bean with "&lt;span style="color: orange;"&gt;name&lt;/span&gt;" Oleg.&lt;br /&gt;&lt;pre class="brush:java"&gt;&amp;nbsp;&lt;br /&gt;FacesAccessor.mapVariable2ValueExpression("personBean", "#{personsBean.person['Oleg']}");&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;In a facelets page, say so, &lt;span style="color: orange;"&gt;personDetail.xhtml&lt;/span&gt;, we can write:&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt;      xmlns:ui="http://java.sun.com/jsf/facelets"&lt;br /&gt;      xmlns:h="http://java.sun.com/jsf/html"&amp;gt;&lt;br /&gt;&amp;lt;ui:composition&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;    &amp;lt;h:inputText value="#{personBean.name}"/&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;&amp;lt;/ui:composition&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;Note, the reference "&lt;span style="color: orange;"&gt;personBean&lt;/span&gt;" was set in Java. This mapping can be also used in facelets in declarative way via &lt;span style="color: orange;"&gt;ui:include&lt;/span&gt; / &lt;span style="color: orange;"&gt;ui:param&lt;/span&gt;.&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt;      xmlns:ui="http://java.sun.com/jsf/facelets"&amp;gt;&lt;br /&gt;&amp;lt;ui:composition&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;    &amp;lt;ui:include src="personDetail.xhtml"&amp;gt;&lt;br /&gt;        &amp;lt;ui:param name="personBean" value="#{personsBean.person['Oleg']}"/&amp;gt;&lt;br /&gt;    &amp;lt;/ui:include&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;&amp;lt;/ui:composition&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;The next two methods are used to create &lt;span style="color: orange;"&gt;MethodExpression&lt;/span&gt; / &lt;span style="color: orange;"&gt;MethodExpressionActionListener&lt;/span&gt; programmatically. They are handy if you use component binding via "&lt;span style="color: orange;"&gt;binding&lt;/span&gt;" attribute or create some model classes &lt;span style="color: orange;"&gt;&lt;/span&gt;in Java.&lt;br /&gt;&lt;pre class="brush:java"&gt;public static MethodExpression createMethodExpression(String valueExpression,&lt;br /&gt;                                                      Class&amp;lt;?&amp;gt; expectedReturnType,&lt;br /&gt;                                                      Class&amp;lt;?&amp;gt;[] expectedParamTypes) {&lt;br /&gt;    MethodExpression methodExpression = null;&lt;br /&gt;    try {&lt;br /&gt;        FacesContext fc = FacesContext.getCurrentInstance();&lt;br /&gt;        ExpressionFactory factory = fc.getApplication().getExpressionFactory();&lt;br /&gt;        methodExpression = factory.&lt;br /&gt;            createMethodExpression(fc.getELContext(), valueExpression, expectedReturnType, expectedParamTypes);&lt;br /&gt;    } catch (Exception e) {&lt;br /&gt;        throw new FacesException("Method expression '" + valueExpression + "' could not be created.");&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    return methodExpression;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static MethodExpressionActionListener createMethodActionListener(String valueExpression,&lt;br /&gt;                                                                        Class&amp;lt;?&amp;gt; expectedReturnType,&lt;br /&gt;                                                                        Class&amp;lt;?&amp;gt;[] expectedParamTypes) {&lt;br /&gt;    MethodExpressionActionListener actionListener = null;&lt;br /&gt;    try {&lt;br /&gt;        actionListener = new MethodExpressionActionListener(createMethodExpression(&lt;br /&gt;            valueExpression, expectedReturnType, expectedParamTypes));&lt;br /&gt;    } catch (Exception e) {&lt;br /&gt;        throw new FacesException("Method expression for ActionListener '" + valueExpression&lt;br /&gt;                          + "' could not be created.");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return actionListener;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;u&gt;Using:&lt;/u&gt;&lt;br /&gt;In one of my projects I have created PrimeFaces &lt;span style="color: orange;"&gt;MenuModel &lt;/span&gt; with menu items programmatically.&lt;br /&gt;&lt;pre class="brush:java"&gt;MenuItem mi = new MenuItem();&lt;br /&gt;mi.setAjax(true);&lt;br /&gt;mi.setValue(...);&lt;br /&gt;mi.setProcess(...);&lt;br /&gt;mi.setUpdate(...);&lt;br /&gt;mi.setActionExpression(FacesAccessor.createMethodExpression(&lt;br /&gt;    "#{navigationContext.setBreadcrumbSelection}", String.class, new Class[] {}));&lt;br /&gt;&lt;br /&gt;UIParameter param = new UIParameter();&lt;br /&gt;param.setId(...);&lt;br /&gt;param.setName(...);&lt;br /&gt;param.setValue(...);&lt;br /&gt;mi.getChildren().add(param);&lt;br /&gt;&lt;/pre&gt;Do you have nice methods you want to share here? Tips / tricks are welcome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-1096589826212222922?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/1096589826212222922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/11/5-useful-methods-jsf-developers-should.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1096589826212222922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1096589826212222922'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/11/5-useful-methods-jsf-developers-should.html' title='5 useful methods JSF developers should know'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-2575874497621925745</id><published>2011-10-29T13:48:00.000-07:00</published><updated>2011-10-29T13:48:53.745-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><title type='text'>Fix for CSS opacity in Internet Explorer</title><content type='html'>How to set CSS opacity in Internet Explorer? It's easy for good browsers like Firefox, Google Chrome or new IE9:&lt;br /&gt;&lt;pre class="brush:css"&gt;opacity: 0.5;&lt;br /&gt;&lt;/pre&gt;For old Safary versions you probably also need&lt;br /&gt;&lt;pre class="brush:css"&gt;-khtml-opacity: 0.5;&lt;br /&gt;&lt;/pre&gt;For IE6, IE7 you can write&lt;br /&gt;&lt;pre class="brush:css"&gt;filter: alpha(opacity=50);&lt;br /&gt;&lt;/pre&gt;and for IE8&lt;br /&gt;&lt;pre class="brush:css"&gt;-ms-filter: "alpha(opacity=50)";&lt;br /&gt;&lt;/pre&gt;Saidly, but filter with opacity value in IE isn't enough. Element should be positioned, in order that opacity would work in IE. If the element doesn't have a position, there is a little trick in order to get it working. Add '&lt;span style="color: orange;"&gt;zoom: 1&lt;/span&gt;' to your CSS.&lt;br /&gt;&lt;pre class="brush:css"&gt;filter: alpha(opacity=50);        // IE6, IE7&lt;br /&gt;-ms-filter: "alpha(opacity=50)"; // IE8&lt;br /&gt;zoom: 1;&lt;br /&gt;&lt;/pre&gt;I have faced this problem with Schedule component in PrimeFaces. The button "&lt;span style="color: orange;"&gt;today&lt;/span&gt;" is not disabled in IE7 for the current day although it has the jQuery UI style &lt;span style="color: orange;"&gt;.ui-state-disabled&lt;/span&gt;. The fix would be&lt;br /&gt;&lt;pre class="brush:css"&gt;/* IE7 hack */&lt;br /&gt;div.fc-button-today.ui-state-disabled {&lt;br /&gt;    *zoom: 1;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: orange;"&gt;*&lt;/span&gt; means the style is applied for IE7 only.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-2575874497621925745?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/2575874497621925745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/10/fix-for-css-opacity-in-internet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2575874497621925745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2575874497621925745'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/10/fix-for-css-opacity-in-internet.html' title='Fix for CSS opacity in Internet Explorer'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-8159626596403935856</id><published>2011-10-07T03:45:00.000-07:00</published><updated>2011-10-07T03:47:31.035-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Jersey'/><title type='text'>Draw masked images with Java 2D API and Jersey servlet</title><content type='html'>The task I had for one Struts web project was the dynamic image painting. You maybe know a small flag icon in MS Outlook which indicates message states. It can be red, green, etc. We needed the similar flag icon with configurable colors. The color is variable and thus unknown a priori - it can be set dynamically in backend and passed to front-end. I develop Struts web applications with JSF in mind. We can't use custom JSF resource handler in Struts, but we can use servlets. A HTTP servlet is able to catch GET requests causing by Struts or JSF image tags and render an image. All parameters should be passed in URL - they should be parts of URL. We need following parameters:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;image format like "png" or "jpg"&lt;/li&gt;&lt;li&gt;file name of base image&lt;/li&gt;&lt;li&gt;file name of mask image&lt;/li&gt;&lt;li&gt;color (in HEX without leading "#" or "0x" signs)&lt;/li&gt;&lt;/ul&gt;An URL-example is&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;nbsp;&lt;br /&gt;http://host:port/webappcontext/masked/png/flag/flag-mask/FF0000/mfile.imgdrawer&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;To save me pain for manually parsing of URL string and extraction of all parameters I have took &lt;a href="http://jersey.java.net/"&gt;Jersey&lt;/a&gt; - reference implementation for building RESTful Web services. Jersey's RESTful Web services are implemented as servlet which takes requests and does some actions according to URL structure. We just need to implement such actions. My action (and task) is image drawing / painting. That occurs by means of Java 2D API - a set of classes for advanced 2D graphics and imaging. Let me show the end result at first. Base image looks as follows&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-OQbvUK4Vp4I/To7THWCthhI/AAAAAAAAAFw/npnoKCxpXj8/s1600/DrawBaseImage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-OQbvUK4Vp4I/To7THWCthhI/AAAAAAAAAFw/npnoKCxpXj8/s1600/DrawBaseImage.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Mask image looks as follows&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-ADArbxk4K1M/To7TLywa2pI/AAAAAAAAAF0/eNL5Z3u_FU0/s1600/DrawMaskImage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-utVx3Hm-9p8/To7Tksg_wWI/AAAAAAAAAF4/DokKNkgWNFQ/s1600/DrawMaskImage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-utVx3Hm-9p8/To7Tksg_wWI/AAAAAAAAAF4/DokKNkgWNFQ/s1600/DrawMaskImage.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;And now the magic is comming. I'm sending a GET request to draw a red flag (color &lt;span style="color: orange;"&gt;FF0000&lt;/span&gt;) dynamically:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-RJ0XxRuUJF0/To7T-Yjs5CI/AAAAAAAAAF8/yxqXqyYf4DM/s1600/DrawRedMaskedImage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-RJ0XxRuUJF0/To7T-Yjs5CI/AAAAAAAAAF8/yxqXqyYf4DM/s1600/DrawRedMaskedImage.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;I'm sending a GET request to draw a green flag (color &lt;span style="color: orange;"&gt;00FF00&lt;/span&gt;):&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-MScdk0Ri_ZA/To7UFdWClKI/AAAAAAAAAGA/L1op3dSvo3c/s1600/DrawGreenMaskedImage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-MScdk0Ri_ZA/To7UFdWClKI/AAAAAAAAAGA/L1op3dSvo3c/s1600/DrawGreenMaskedImage.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Do you want to see a blue image? No problem, I can type as color &lt;span style="color: orange;"&gt;00ff&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-8IaN1JBm1j0/To7UsXiEf7I/AAAAAAAAAGI/mwUxqeill64/s1600/DrawBlueMaskedImage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-8IaN1JBm1j0/To7UsXiEf7I/AAAAAAAAAGI/mwUxqeill64/s1600/DrawBlueMaskedImage.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-GyqaXeiSB3I/To7UL3JZPZI/AAAAAAAAAGE/vC1JtCJbdYk/s1600/DrawBlueMaskedImage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;/a&gt;&lt;/div&gt;You need four things to achieve that:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1.&lt;/b&gt; Dependencies to Jersey and Java 2D Graphics. Maven users can add these as follows:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;com.sun.jersey&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;jersey-server&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;... last version ...&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;com.sun.media&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;jai_codec&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;... last version ...&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;com.sun.media&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;jai_imageio&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;... last version ...&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;2.&lt;/b&gt; Two image files in the web application. I have placed them under &lt;span style="color: orange;"&gt;webapp/resources/themes/app/images/&lt;/span&gt; and they are called in my case &lt;span style="color: orange;"&gt;flag.png&lt;/span&gt; and &lt;span style="color: orange;"&gt;flag-mask.png&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3.&lt;/b&gt; Configuration for Jersey servlet in &lt;span style="color: orange;"&gt;web.xml&lt;/span&gt;. My configuration is&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;servlet&amp;gt;&lt;br /&gt;    &amp;lt;servlet-name&amp;gt;imagedrawer&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;    &amp;lt;servlet-class&amp;gt;com.sun.jersey.spi.container.servlet.ServletContainer&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;    &amp;lt;init-param&amp;gt;&lt;br /&gt;        &amp;lt;param-name&amp;gt;com.sun.jersey.config.property.packages&amp;lt;/param-name&amp;gt;&lt;br /&gt;        &amp;lt;param-value&amp;gt;ip.client.commons.web.servlet&amp;lt;/param-value&amp;gt;&lt;br /&gt;    &amp;lt;/init-param&amp;gt;&lt;br /&gt;&amp;lt;/servlet&amp;gt;&lt;br /&gt;&amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;    &amp;lt;servlet-name&amp;gt;imagedrawer&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;    &amp;lt;url-pattern&amp;gt;*.imgdrawer&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;Image-URL should be ended with &lt;span style="color: orange;"&gt;imgdrawer&lt;/span&gt; to be able to handled by Jersey servlet. By the way, my FacesServlet is mapped to &lt;span style="color: orange;"&gt;*.jsf&lt;/span&gt; and Struts ActionServlet to &lt;span style="color: orange;"&gt;*.do&lt;/span&gt;. Init parameter &lt;span style="color: orange;"&gt;com.sun.jersey.config.property.packages&lt;/span&gt; points to the Java package where the handler class is placed. Writing of handler class is the step 4.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4.&lt;/b&gt; Handler class which treats GET requests and draws / paints a new masked image by means of Java 2D API. The new image is a composition of two predefined images from the step 2. The mask gets painted and overlapped with the base image. The code is more or less documented, so that I omit any comments :-)&lt;br /&gt;&lt;pre class="brush:java"&gt;/**&lt;br /&gt; * Jersey annotated class for image drawing. Drawed images don't need to be cached server side because they are cached&lt;br /&gt; * proper on the client side. Set "expires" and "max-age" ensure client side caching.&lt;br /&gt; */&lt;br /&gt;@Path("/")&lt;br /&gt;@Produces("image/*")&lt;br /&gt;@Singleton&lt;br /&gt;public class ImageDrawer {&lt;br /&gt;    @Context ServletContext context;&lt;br /&gt;&lt;br /&gt;    /** directory for image files (can be done configurable if needed) */&lt;br /&gt;    private String imageDir = "/resources/themes/app/images/";&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Gets composed image consist of base and mask image.&lt;br /&gt;     *&lt;br /&gt;     * @param  format   format, e.g. "png", "jpg".&lt;br /&gt;     * @param  basefile file name of base image without file extension&lt;br /&gt;     * @param  maskfile file name of mask image without file extension&lt;br /&gt;     * @param  hexcolor color in HEX without leading "#" or "0x" signs&lt;br /&gt;     * @return Response new composed image&lt;br /&gt;     * @throws WebApplicationException thrown exception, 404 or 500 status code.&lt;br /&gt;    */&lt;br /&gt;    @GET&lt;br /&gt;    @Path("/masked/{format}/{basefile}/{maskfile}/{hexcolor}/{img}")&lt;br /&gt;    public Response getImage(@PathParam("format") String format,&lt;br /&gt;                             @PathParam("basefile") String basefile,&lt;br /&gt;                             @PathParam("maskfile") String maskfile,&lt;br /&gt;                             @PathParam("hexcolor") String hexcolor) {&lt;br /&gt;        // check parameters&lt;br /&gt;        if (format == null || basefile == null || maskfile == null || hexcolor == null) {&lt;br /&gt;            throw new WebApplicationException(404);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // try to get images from web application&lt;br /&gt;        InputStream is1 = context.getResourceAsStream(imageDir + basefile + "." + format);&lt;br /&gt;        if (is1 == null) {&lt;br /&gt;            throw new WebApplicationException(404);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        InputStream is2 = context.getResourceAsStream(imageDir + maskfile + "." + format);&lt;br /&gt;        if (is2 == null) {&lt;br /&gt;            throw new WebApplicationException(404);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        RenderedImage img1 = renderImage(is1);&lt;br /&gt;        RenderedImage img2 = renderImage(is2);&lt;br /&gt;&lt;br /&gt;        // convert HEX to RGB&lt;br /&gt;        Color color = Color.decode("0x" + hexcolor);&lt;br /&gt;&lt;br /&gt;        // draw the new image&lt;br /&gt;        BufferedImage resImage = drawMaskedImage(img1, img2, color);&lt;br /&gt;&lt;br /&gt;        byte[] resImageBytes = null;&lt;br /&gt;        ByteArrayOutputStream baos = new ByteArrayOutputStream();&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            // use Apache IO&lt;br /&gt;            ImageIO.write(resImage, format, baos);&lt;br /&gt;            baos.flush();&lt;br /&gt;            resImageBytes = baos.toByteArray();&lt;br /&gt;        } catch (IOException e) {&lt;br /&gt;            throw new WebApplicationException(500);&lt;br /&gt;        } finally {&lt;br /&gt;            try {&lt;br /&gt;                baos.close();&lt;br /&gt;            } catch (IOException e) {&lt;br /&gt;                ;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // cache in browser forever&lt;br /&gt;        CacheControl cacheControl = new CacheControl();&lt;br /&gt;        cacheControl.setMaxAge(Integer.MAX_VALUE);&lt;br /&gt;&lt;br /&gt;        return Response.ok(resImageBytes, "image/" + format).cacheControl(cacheControl)&lt;br /&gt;                       .expires(new Date(Long.MAX_VALUE)).build();&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    // Utilities (written not by me, copyright &amp;copy;)&lt;br /&gt;&lt;br /&gt;    private RenderedImage renderImage(InputStream in) {&lt;br /&gt;        SeekableStream stream = createSeekableStream(in);&lt;br /&gt;        boolean isImageIOAvailable = false;&lt;br /&gt;        if (Thread.currentThread().getContextClassLoader().&lt;br /&gt;            getResource("META-INF/services/javax.imageio.spi.ImageReaderSpi") != null) {&lt;br /&gt;            isImageIOAvailable = true;&lt;br /&gt;        }&lt;br /&gt;        return JAI.create(isImageIOAvailable ? "ImageRead" : "stream", stream);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private BufferedImage drawMaskedImage(RenderedImage orig, RenderedImage mask, Color color) {&lt;br /&gt;        BufferedImage overlay = manipulateImage(mask, null);&lt;br /&gt;        return manipulateImage(orig, new ImageManipulator() {&lt;br /&gt;            public void manipulate(final Graphics2D g2d) {&lt;br /&gt;                float[] scaleFactors = new float[] {&lt;br /&gt;                2f * (color.getRed() / 255f), 2f * (color.getGreen() / 255f),&lt;br /&gt;                2f * (color.getBlue() / 255f), color.getAlpha() / 255f};&lt;br /&gt;                float[] offsets = new float[] {0, 0, 0, 0};&lt;br /&gt;                g2d.drawImage(overlay, new RescaleOp(scaleFactors, offsets, null), 0, 0);&lt;br /&gt;            }&lt;br /&gt;        });&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private BufferedImage manipulateImage(RenderedImage orig, ImageManipulator manipulator) {&lt;br /&gt;        BufferedImage image;&lt;br /&gt;        boolean drawOriginal = false;&lt;br /&gt;        ColorModel colorModel = orig.getColorModel();&lt;br /&gt;        int colorSpaceType = colorModel.getColorSpace().getType();&lt;br /&gt;        if (colorModel.getPixelSize() &amp;gt;= 4 &amp;amp;&amp;amp; colorSpaceType != ColorSpace.TYPE_GRAY) {&lt;br /&gt;            image = new RenderedImageAdapter(orig).getAsBufferedImage();&lt;br /&gt;        } else if (colorSpaceType == ColorSpace.TYPE_GRAY) {&lt;br /&gt;            image = new BufferedImage(orig.getWidth(), orig.getHeight(), BufferedImage.TYPE_INT_ARGB);&lt;br /&gt;            drawOriginal = true;&lt;br /&gt;        } else {&lt;br /&gt;            image = new BufferedImage(orig.getWidth(), orig.getHeight(), BufferedImage.TYPE_BYTE_INDEXED);&lt;br /&gt;            drawOriginal = true;&lt;br /&gt;        }&lt;br /&gt;   &lt;br /&gt;        Graphics2D g2d = image.createGraphics();&lt;br /&gt;        if (drawOriginal) {&lt;br /&gt;            g2d.drawImage(new RenderedImageAdapter(orig).getAsBufferedImage(), 0, 0, null);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        if (manipulator != null) {&lt;br /&gt;            manipulator.manipulate(g2d);&lt;br /&gt;        }&lt;br /&gt;    &lt;br /&gt;        return image;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private interface ImageManipulator {void manipulate(Graphics2D g2d);} &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-8159626596403935856?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/8159626596403935856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/10/draw-masked-images-with-java-2d-api-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/8159626596403935856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/8159626596403935856'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/10/draw-masked-images-with-java-2d-api-and.html' title='Draw masked images with Java 2D API and Jersey servlet'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-OQbvUK4Vp4I/To7THWCthhI/AAAAAAAAAFw/npnoKCxpXj8/s72-c/DrawBaseImage.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-1888908101524763659</id><published>2011-10-06T06:12:00.000-07:00</published><updated>2011-10-06T06:20:20.409-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Facelets'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='HTML5'/><title type='text'>Facelets with HTML5</title><content type='html'>After reading &lt;a href="http://stackoverflow.com/questions/2935759/is-it-possible-to-use-jsffacelets-with-html-4-5"&gt;this post on StackOverflow&lt;/a&gt; I have decided to use &lt;span style="color: orange;"&gt;HTML5 DOCTYPE&lt;/span&gt; in JSF. Why to write long DOCTYPE with DTD, (X)HTML, Transitional, etc. like this one&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &lt;br /&gt;          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt;      xmlns:f="http://java.sun.com/jsf/core"&lt;br /&gt;      xmlns:h="http://java.sun.com/jsf/html"&lt;br /&gt;      ... &amp;gt;&lt;br /&gt;      &lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;if we can write much simpler &lt;span style="color: orange;"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;?&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt;      xmlns:f="http://java.sun.com/jsf/core"&lt;br /&gt;      xmlns:h="http://java.sun.com/jsf/html"&lt;br /&gt;      ... &amp;gt;&lt;br /&gt;      &lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;Using &lt;span style="color: orange;"&gt;HTML5 DOCTYPE&lt;/span&gt; doesn't have side effects with Facelets parser and works fine in all browsers expect of IE6 which will render pages in quirks mode. IE6 usage is decreasing last years and it's not supported by many JSF libraries (like PrimeFaces) anymore. So, it doesn't hurt. If you are using HTML5 specific elements (e.g. file upload in PrimeFaces) and the browser doesn't support them, fallbacks will be applied. HTML5 specific elements will be gracefully degraded to HTML4.&lt;br /&gt;&lt;br /&gt;One small issue I had during my changes of DOCTYPE was the entity &lt;span style="color: orange;"&gt;&amp;amp;nbsp;&lt;/span&gt; which I sometimes use for non-breaking space. The Facelets parser says&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;nbsp;&lt;br /&gt;The entity "nbsp" was referenced, but not declared.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;The solution is to replace &lt;span style="color: orange;"&gt;&amp;amp;nbsp;&lt;/span&gt; by the character reference &lt;span style="color: orange;"&gt;&amp;amp;#160;&lt;/span&gt; Also other entities like &lt;span style="color: orange;"&gt;&amp;amp;copy;&lt;/span&gt; should be replaced by character references. Apart from that JSF components which I use in my web apps are okey so far.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Summary:&lt;/u&gt; Using of &lt;span style="color: orange;"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt; in Facelets is highly recommended. It's simple and future-proof.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-1888908101524763659?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/1888908101524763659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/10/facelets-with-html5.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1888908101524763659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1888908101524763659'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/10/facelets-with-html5.html' title='Facelets with HTML5'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-2614815942873659916</id><published>2011-09-29T02:57:00.001-07:00</published><updated>2012-02-20T11:24:57.467-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Atmosphere'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='Comet'/><title type='text'>Atmosphere and JSF are good friends</title><content type='html'>Decision to write this long article was driven by PrimeFaces community. People have troubles to develop web applications with server push techniques. Even with &lt;a href="http://atmosphere.java.net/"&gt;Atmosphere&lt;/a&gt; - framework for building portable Comet and WebSocket based applications. Portable means it can run on Tomcat, JBoss, Jetty, GlassFish or any other application server which supports Servlet specification 2.5 or higher. If you want to be independent on underlying server and don't want to have headaches during implementation, use Atmosphere framework. It simplifies development and can be easy integrated into JSF or any other web frameworks (don't matter). I read Atmosphere doesn't play nice with JSF or similar. PrimeFaces had a special Athmosphere handler for JSF in 2.2.1. But that's all is not necessary. It doesn't matter what for a web framework you use - the intergration is the same. My intention is to show how to set up a bidirectional communication between client and server by using of Atmosphere. My open source project "&lt;a href="http://code.google.com/p/online-whiteboard/"&gt;Collaborative Online-Whiteboard&lt;/a&gt;" demonstrates that this approach works well for all three transport protocols - Long-Polling, Streaming and WebSocket. This is an academic web application built on top of the Raphaël / jQuery JavaScript libraries, Atmosphere framework and PrimeFaces. You can open two browser windows (browser should support WebSocket) and try to draw shapes, to input text, to paste image, icon, to remove, clone, move elements etc.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-j2BYnogKhfw/ToQ6H_2eLtI/AAAAAAAAAFo/lmA1z1Ukxd0/s1600/whiteboard.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="519" src="http://3.bp.blogspot.com/-j2BYnogKhfw/ToQ6H_2eLtI/AAAAAAAAAFo/lmA1z1Ukxd0/s640/whiteboard.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;We need a little theory at first. For bidirectional communication we need to define a Topic at first (called sometimes "channel"). Users subscribe to the Topic and act as Subscribers to receive new data (called updates or messages as well). A subscriber acts at the same time as Publisher and can send data to all subscribers (broadcasting). Topic can be expressed by an unique URL - from the technical point of view. URL should be specified in such a manner that all bidirectional communication goes through &lt;span style="color: orange;"&gt;AtmosphereServlet&lt;/span&gt;. JSF requests should go through &lt;span style="color: orange;"&gt;FacesServlet&lt;/span&gt;. This is a very important decision and probably the reason why Atmosphere integration in various web frameworks like JSF and Struts sometimes fails. Bidirectional communication should be lightweight and doesn't run all JSF lifecycle phases! This can be achieved by proper servlet-mapping in &lt;span style="color: orange;"&gt;web.xml&lt;/span&gt;. The picture below should demonstrate the architecture (example of my open source project).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-aWeGVOSp3-s/ToQ6SyBBSzI/AAAAAAAAAFs/EQUWFJM5dCo/s1600/whiteboard-architecture.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-aWeGVOSp3-s/ToQ6SyBBSzI/AAAAAAAAAFs/EQUWFJM5dCo/s1600/whiteboard-architecture.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;For my use case I need messages in JSON format, but generally any data can be passed over bidirectional channel (XML, HTML). What is the Topic exactly? It depends on web application how you define the Topic. You can let user types it self (e.g. in chat applications) or make it predefined. In my application I equate Topic with Whiteboard-Id which is generated as UUID. Furthermore, I have introduced User-Id (= Publisher-Id) as well and called it Sender. Sender serves as identificator to filter Publisher out of all Subscribers. Publisher is normally not interested in self notification. I'm going to show using of Sender later. My Topic-URL follows this pattern&lt;br /&gt;&lt;pre class="brush:xml"&gt;http://host:port/pubsub/{topic}/{sender}.topic&lt;br /&gt;&lt;/pre&gt;and looks like e.g. as&lt;br /&gt;&lt;pre class="brush:xml"&gt;http://localhost:8080/pubsub/ea288b4c-f2d5-467f-8d6c-8d23d6ab5b11/e792f55e-2309-4770-9c48-de75354f395d.topic&lt;br /&gt;&lt;/pre&gt;I use Atmosphere with &lt;a href="http://jersey.java.net/"&gt;Jersey&lt;/a&gt; I think it's a better way than to write Atmosphere handlers or try to integrate MeteorServlet. Therefore, to start using of Atmosphere, you need a dependency to current Atmosphere and Jersey. Below is a dependency configuration for Maven users. Note: I cut logging off.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;org.atmosphere&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;atmosphere-jersey&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;0.8-SNAPSHOT&amp;lt;/version&amp;gt;&lt;br /&gt;    &amp;lt;exclusions&amp;gt;&lt;br /&gt;        &amp;lt;exclusion&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;org.atmosphere&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;atmosphere-ping&amp;lt;/artifactId&amp;gt;&lt;br /&gt;        &amp;lt;/exclusion&amp;gt;&lt;br /&gt;        &amp;lt;exclusion&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;org.slf4j&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;slf4j-api&amp;lt;/artifactId&amp;gt;&lt;br /&gt;        &amp;lt;/exclusion&amp;gt;&lt;br /&gt;    &amp;lt;/exclusions&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;org.apache.geronimo.specs&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;geronimo-servlet_3.0_spec&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;org.slf4j&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;slf4j-api&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;1.6.2&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;org.slf4j&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;slf4j-nop&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;1.6.2&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;/pre&gt;The next step is to add Atmosphere-jQuery plugin to the client side. This plugin can be downloaded from the Atmosphere's homepage. After placing &lt;span style="color: orange;"&gt;jquery.atmosphere.js&lt;/span&gt; under &lt;span style="color: orange;"&gt;webapp/resources/js&lt;/span&gt; you can include it with&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;h:outputScript library="js" name="jquery.atmosphere.js" target="head"/&amp;gt;&lt;br /&gt;&lt;/pre&gt;Yes, I know that Atmosphere can load &lt;span style="color: orange;"&gt;jquery.atmosphere.js&lt;/span&gt; from JAR file in classpath, but a manual include is better in JSF environment. Now we are able to subscribe to the Topic and communicate with the server on the client side. There are two calls: &lt;span style="color: orange;"&gt;jQuery.atmosphere.subscribe()&lt;/span&gt; and &lt;span style="color: orange;"&gt;jQuery.atmosphere.response.push()&lt;/span&gt;. To establish a bidirectional communication, you need to call &lt;span style="color: orange;"&gt;subscribe()&lt;/span&gt;. You have to call this method just once when page has been loaded. After that the method &lt;span style="color: orange;"&gt;push()&lt;/span&gt; is responsible for data publushing to all subsribers. In the mentioned above web application I have an JavaScript object &lt;span style="color: orange;"&gt;WhiteboardDesigner&lt;/span&gt; which encapsulates the Atmosphere's &lt;span style="color: orange;"&gt;subscribe()&lt;/span&gt; call in the method &lt;span style="color: orange;"&gt;subscribePubSub()&lt;/span&gt;.&lt;br /&gt;&lt;pre class="brush:js"&gt;// Subscribes to bidirectional channel.&lt;br /&gt;// This method should be called once the web-application is ready to use.&lt;br /&gt;this.subscribePubSub = function() {&lt;br /&gt;  jQuery.atmosphere.subscribe(&lt;br /&gt;    this.pubSubUrl,&lt;br /&gt;    this.pubSubCallback,&lt;br /&gt;    jQuery.atmosphere.request = {&lt;br /&gt;      transport: this.pubSubTransport,&lt;br /&gt;      maxRequest: 100000000&lt;br /&gt;    });&lt;br /&gt;    &lt;br /&gt;    this.connectedEndpoint = jQuery.atmosphere.response;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The first parameter &lt;span style="color: orange;"&gt;this.pubSubUrl&lt;/span&gt; is the shown above Topic-URL. The second parameter &lt;span style="color: orange;"&gt;this.pubSubCallback&lt;/span&gt; is the callback function. The third parameter is the request configuration which keeps among other things transport protocol defined in &lt;span style="color: orange;"&gt;this.pubSubTransport&lt;/span&gt;: "long-polling", "streaming" or "websocket". The last line assigns &lt;span style="color: orange;"&gt;jQuery.atmosphere.response&lt;/span&gt; the variable &lt;span style="color: orange;"&gt;this.connectedEndpoint&lt;/span&gt; which allows us data publishing via &lt;span style="color: orange;"&gt;push()&lt;/span&gt;. So now when new data being received, the callback function &lt;span style="color: orange;"&gt;this.pubSubUrl&lt;/span&gt; gets called. Inside of the callback we can extract received data from response object. You can get the idea how to handle broadcasted data from my example:&lt;br /&gt;&lt;pre class="brush:js"&gt;// Callback method defined in the subscribePubSub() method.&lt;br /&gt;// This method is always called when new data (updates) are available on server side.&lt;br /&gt;this.pubSubCallback = function(response) {&lt;br /&gt;  if (response.transport != 'polling' &amp;amp;&amp;amp;&lt;br /&gt;      response.state != 'connected' &amp;amp;&amp;amp;&lt;br /&gt;      response.state != 'closed' &amp;amp;&amp;amp; response.status == 200) {&lt;br /&gt;      var data = response.responseBody;&lt;br /&gt;      if (data.length &amp;gt; 0) {&lt;br /&gt;        // convert to JavaScript object&lt;br /&gt;        var jsData = JSON.parse(data);&lt;br /&gt;&lt;br /&gt;       // get broadcasted data&lt;br /&gt;        var action = jsData.action;&lt;br /&gt;        var sentProps = (jsData.element != null ? jsData.element.properties : null);&lt;br /&gt;        switch (action) {&lt;br /&gt;          case "create" :&lt;br /&gt;            ...&lt;br /&gt;            break;&lt;br /&gt;          case "update" :&lt;br /&gt;            ...&lt;br /&gt;            break;&lt;br /&gt;          case "remove" :&lt;br /&gt;            ...&lt;br /&gt;            break;&lt;br /&gt;          ... &lt;br /&gt;          default :&lt;br /&gt;        }&lt;br /&gt;        ...&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;To publish data over the Topic-URL you need to call &lt;span style="color: orange;"&gt;this.connectedEndpoint.push()&lt;/span&gt;. &lt;span style="color: orange;"&gt;this.connectedEndpoint&lt;/span&gt; is a defined above shortcut for &lt;span style="color: orange;"&gt;jQuery.atmosphere.response&lt;/span&gt;. I call it in my example for created whiteboard elements as follows (just an example):&lt;br /&gt;&lt;pre class="brush:js"&gt;// Send changes to server when a new image was created.&lt;br /&gt;this.sendChanges({&lt;br /&gt;  "action": "create",&lt;br /&gt;  "element": {&lt;br /&gt;    "type": "Image",&lt;br /&gt;    "properties": {&lt;br /&gt;      "uuid": ...,&lt;br /&gt;      "x": ...,&lt;br /&gt;      "y": ...,&lt;br /&gt;      "url": ...,&lt;br /&gt;      "width": ...,&lt;br /&gt;      "height": ...&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;// Send any changes on client side to the server.&lt;br /&gt;this.sendChanges = function(jsObject) {&lt;br /&gt;  // set timestamp&lt;br /&gt;  var curDate = new Date();&lt;br /&gt;  jsObject.timestamp = curDate.getTime() + curDate.getTimezoneOffset() * 60000;&lt;br /&gt;&lt;br /&gt;  // set user&lt;br /&gt;  jsObject.user = this.user;&lt;br /&gt;&lt;br /&gt;  // set whiteboard Id&lt;br /&gt;  jsObject.whiteboardId = this.whiteboardId;&lt;br /&gt;&lt;br /&gt;  var outgoingMessage = JSON.stringify(jsObject);&lt;br /&gt;&lt;br /&gt;  // send changes to all subscribed clients&lt;br /&gt;  this.connectedEndpoint.push(this.pubSubUrl, null, jQuery.atmosphere.request = {data: 'message=' + outgoingMessage});&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Passed JavaScript object &lt;span style="color: orange;"&gt;jsObject&lt;/span&gt; is converted to JSON via &lt;span style="color: orange;"&gt;JSON.stringify(jsObject)&lt;/span&gt; befor it's sending to the server.&lt;br /&gt;&lt;br /&gt;What is necessary on the server side? Calls &lt;span style="color: orange;"&gt;jQuery.atmosphere.subscribe()&lt;/span&gt; and &lt;span style="color: orange;"&gt;jQuery.atmosphere.response.push()&lt;/span&gt; have to be caught on the server side. I use Jersey and its annotations to catch GET- / POST-requests for the certain Topic-URL in a declarative way. For that are responsible annotations &lt;span style="color: orange;"&gt;@GET&lt;/span&gt;, &lt;span style="color: orange;"&gt;@POST&lt;/span&gt; und &lt;span style="color: orange;"&gt;@PATH&lt;/span&gt;. I have developed the class &lt;span style="color: orange;"&gt;WhiteboardPubSub&lt;/span&gt; to catch the Topic-URL by means of &lt;span style="color: orange;"&gt;@Path("/pubsub/{topic}/{sender}")&lt;/span&gt;. With &lt;span style="color: orange;"&gt;@GET&lt;/span&gt; annotated method &lt;span style="color: orange;"&gt;subscribe()&lt;/span&gt; catches the call &lt;span style="color: orange;"&gt;jQuery.atmosphere.subscribe()&lt;/span&gt;. This method tells Atmosphere to suspend the current request until an event occurs. Topic (= Broadcaster) is also created in this method. Topic-String is extracted by the annotation &lt;span style="color: orange;"&gt;@PathParam&lt;/span&gt; from the Topic-URL. You can imagine a Broadcaster as a queue. As soon as a new message lands in the queue all subscribers get notified (browsers which are connected with Topic get this message). With &lt;span style="color: orange;"&gt;@POST&lt;/span&gt; annotated method &lt;span style="color: orange;"&gt;publish()&lt;/span&gt; catches the call &lt;span style="color: orange;"&gt;jQuery.atmosphere.response.push()&lt;/span&gt;. Client's data will be processed there and broadcasted to all subscribed connections. This occurs independent from the underlying transport protocol.&lt;br /&gt;&lt;pre class="brush:java"&gt;@Path("/pubsub/{topic}/{sender}")&lt;br /&gt;@Produces("text/html;charset=ISO-8859-1")&lt;br /&gt;public class WhiteboardPubSub&lt;br /&gt;{&lt;br /&gt;  private @PathParam("topic") Broadcaster topic;&lt;br /&gt;&lt;br /&gt;  @GET&lt;br /&gt;  public SuspendResponse&amp;lt;String&amp;gt; subscribe() {&lt;br /&gt;    return new SuspendResponse.SuspendResponseBuilder&amp;lt;String&amp;gt;().&lt;br /&gt;               broadcaster(topic).outputComments(true).build();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @POST&lt;br /&gt;  @Broadcast&lt;br /&gt;  public String publish(@FormParam("message") String message,&lt;br /&gt;                      @PathParam("sender") String sender,&lt;br /&gt;                      @Context AtmosphereResource resource) {&lt;br /&gt;    // find current sender in all suspended resources and&lt;br /&gt;    // remove it from the notification&lt;br /&gt;    Collection&amp;lt;AtmosphereResource&amp;lt;?, ?&amp;gt;&amp;gt; ars = topic.getAtmosphereResources();&lt;br /&gt;    if (ars == null) {&lt;br /&gt;      return "";&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    Set&amp;lt;AtmosphereResource&amp;lt;?, ?&amp;gt;&amp;gt; arsSubset = new HashSet&amp;lt;AtmosphereResource&amp;lt;?, ?&amp;gt;&amp;gt;();&lt;br /&gt;    HttpServletRequest curReq = null;&lt;br /&gt;    for (AtmosphereResource ar : ars) {&lt;br /&gt;      Object req = ar.getRequest();&lt;br /&gt;      if (req instanceof HttpServletRequest) {&lt;br /&gt;        String pathInfo = ((HttpServletRequest)req).getPathInfo();&lt;br /&gt;        String resSender = pathInfo.substring(pathInfo.lastIndexOf('/') + 1);&lt;br /&gt;        if (!sender.equals(resSender)) {&lt;br /&gt;          arsSubset.add(ar);&lt;br /&gt;        } else {&lt;br /&gt;          curReq = (HttpServletRequest) req;&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (curReq == null) {&lt;br /&gt;      curReq = (HttpServletRequest) resource.getRequest();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // process current message (JSON) and create a new one (JSON) for subscribed clients&lt;br /&gt;    String newMessage = WhiteboardUtils.updateWhiteboardFromJson(curReq, message);&lt;br /&gt;&lt;br /&gt;    // broadcast subscribed clients except sender&lt;br /&gt;    topic.broadcast(newMessage, arsSubset);&lt;br /&gt;&lt;br /&gt;    return "";&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;In my case the method &lt;span style="color: orange;"&gt;publish()&lt;/span&gt; looks for sender (= publisher of this message) among all subscribers and removes it from the notification. It looks a little bit complicated. In simple case you can write&lt;br /&gt;&lt;pre class="brush:java"&gt;@POST&lt;br /&gt;@Broadcast&lt;br /&gt;public Broadcastable publish(@FormParam("message") String message) {&lt;br /&gt;  return new Broadcastable(message, "", topic);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;and that's all! The last step is the mentioned above configuration in &lt;span style="color: orange;"&gt;web.xml&lt;/span&gt;. &lt;span style="color: orange;"&gt;*.jsf&lt;/span&gt; requests should be mapped to &lt;span style="color: orange;"&gt;FacesServlet&lt;/span&gt; and &lt;span style="color: orange;"&gt;*.topic&lt;/span&gt; requests to &lt;span style="color: orange;"&gt;AtmosphereServlet&lt;/span&gt;. AtmosphereServlet can be configured comprehensively. Important configuration parameter is &lt;span style="color: orange;"&gt;com.sun.jersey.config.property.packages&lt;/span&gt;. With this parameter you can tell Jersey where the annotated class is located (in my case &lt;span style="color: orange;"&gt;WhiteboardPubSub&lt;/span&gt;). In my example Jersey scans the directory &lt;span style="color: orange;"&gt;com.googlecode.whiteboard.pubsub&lt;/span&gt;.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;!-- Faces Servlet --&amp;gt;&lt;br /&gt;&amp;lt;servlet&amp;gt;&lt;br /&gt;  &amp;lt;servlet-name&amp;gt;Faces Servlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;  &amp;lt;servlet-class&amp;gt;javax.faces.webapp.FacesServlet&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;  &amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;&lt;br /&gt;&amp;lt;/servlet&amp;gt;&lt;br /&gt;&amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;  &amp;lt;servlet-name&amp;gt;Faces Servlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;  &amp;lt;url-pattern&amp;gt;*.jsf&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- Atmosphere Servlet --&amp;gt;&lt;br /&gt;&amp;lt;servlet&amp;gt;&lt;br /&gt;  &amp;lt;description&amp;gt;AtmosphereServlet&amp;lt;/description&amp;gt;&lt;br /&gt;  &amp;lt;servlet-name&amp;gt;AtmosphereServlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;  &amp;lt;servlet-class&amp;gt;org.atmosphere.cpr.AtmosphereServlet&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;  &amp;lt;init-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;com.sun.jersey.config.property.resourceConfigClass&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;com.sun.jersey.api.core.PackagesResourceConfig&amp;lt;/param-value&amp;gt;&lt;br /&gt;  &amp;lt;/init-param&amp;gt;&lt;br /&gt;  &amp;lt;init-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;com.sun.jersey.config.property.packages&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;com.googlecode.whiteboard.pubsub&amp;lt;/param-value&amp;gt;&lt;br /&gt;  &amp;lt;/init-param&amp;gt;&lt;br /&gt;  &amp;lt;init-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;org.atmosphere.useWebSocket&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;&lt;br /&gt;  &amp;lt;/init-param&amp;gt;&lt;br /&gt;  &amp;lt;init-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;org.atmosphere.useNative&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;&lt;br /&gt;  &amp;lt;/init-param&amp;gt;&lt;br /&gt;  &amp;lt;init-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;org.atmosphere.cpr.WebSocketProcessor&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;org.atmosphere.cpr.HttpServletRequestWebSocketProcessor&amp;lt;/param-value&amp;gt;&lt;br /&gt;  &amp;lt;/init-param&amp;gt;&lt;br /&gt;  &amp;lt;init-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;org.atmosphere.cpr.broadcastFilterClasses&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;org.atmosphere.client.JavascriptClientFilter&amp;lt;/param-value&amp;gt;&lt;br /&gt;  &amp;lt;/init-param&amp;gt;&lt;br /&gt;  &amp;lt;load-on-startup&amp;gt;2&amp;lt;/load-on-startup&amp;gt;&lt;br /&gt;&amp;lt;/servlet&amp;gt;&lt;br /&gt;&amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;  &amp;lt;servlet-name&amp;gt;AtmosphereServlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;  &amp;lt;url-pattern&amp;gt;*.topic&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;Please check Atmosphere documentation and showcases for more information.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Summary:&lt;/u&gt; We have seen that few things are needed to establish the bidirectional comminication: Topic-URL, callback function for data receiving, &lt;span style="color: orange;"&gt;subsribe()&lt;/span&gt; und &lt;span style="color: orange;"&gt;push()&lt;/span&gt; methods on client side, an Jersey class on server side and configuration in &lt;span style="color: orange;"&gt;web.xml&lt;/span&gt; to bind all parts together. JSF- und Atmosphere-requests should be treated separately. You maybe ask "but what is about the case if I need to access JSF stuff in Atmosphere-request?" For a simple case you can use &lt;a href="http://stackoverflow.com/questions/2633112/jsf-get-managed-bean-by-name"&gt;this technique&lt;/a&gt; to access managed beans. If you want to have a fully access to all JSF stuff you should use &lt;a href="http://ocpsoft.com/java/jsf-java/jsf-20-extension-development-accessing-facescontext-in-a-filter/"&gt;this technique&lt;/a&gt; which allows accessing &lt;span style="color: orange;"&gt;FacesContext&lt;/span&gt; somewhere from the outside.&lt;br /&gt;&lt;br /&gt;P.S. Good news. Atmosphere's lead Jeanfrancois Arcand &lt;a href="http://jfarcand.wordpress.com/2011/09/08/atmosphere-next-update-websocket-javascript-full-docs-and-1-0-0-on-the-horizon/"&gt;announced his intention to pursue the work on Atmosphere&lt;/a&gt;. He can invest more time now in his great framework.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-2614815942873659916?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/2614815942873659916/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/09/atmosphere-and-jsf-are-good-friends.html#comment-form' title='20 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2614815942873659916'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2614815942873659916'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/09/atmosphere-and-jsf-are-good-friends.html' title='Atmosphere and JSF are good friends'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-j2BYnogKhfw/ToQ6H_2eLtI/AAAAAAAAAFo/lmA1z1Ukxd0/s72-c/whiteboard.png' height='72' width='72'/><thr:total>20</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-2003147301065306697</id><published>2011-09-27T03:21:00.000-07:00</published><updated>2011-09-27T03:26:19.750-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><title type='text'>Quick practical introduction to JSDoc (JsDoc Toolkit)</title><content type='html'>Documentation of JavaScript code is a very important part of software development and helps front-end developers to understand code of third-party libraries. There are really well documented libraries. One of them is &lt;a href="http://javaserverfaces.java.net/nonav/docs/2.1/jsdocs/index.html"&gt;Mojarra JavaScript documentation&lt;/a&gt;. Other libraries (and that's a common case) don't have JavaScript documentation at all or don't cover all their features, so that features stay undocumented (I hope PrimeFaces guys read this blog post :-)).&lt;br /&gt;&lt;br /&gt;JSDoc is documentation generated for JavaScript code by means of &lt;a href="http://code.google.com/p/jsdoc-toolkit/"&gt;JsDoc Toolkit&lt;/a&gt;. Documentation is not restricted to multi-page HTML, other formats are possible too. Look-&amp;amp;-feel can be fully customized by templates. In this quick introduction I use built-in templates and would like to show generated JSDoc on example of my open source project "&lt;a href="http://www.fractalsoft.net/whiteboard-websocket/"&gt;Collaborative Online-Whiteboard&lt;/a&gt;". I use following tags in my example:&lt;br /&gt;&lt;br /&gt;&lt;div style="color: orange;"&gt;@fileOverview&lt;/div&gt;This tag allows you to provide documentation for an entire file. It's often used with other tags @author and @version.&lt;br /&gt;&lt;div style="color: orange;"&gt;@class&lt;/div&gt;This tag also allows you to add a description of the JavaScript class (if you write your code in OOP style).&lt;br /&gt;&lt;div style="color: orange;"&gt;@param&lt;/div&gt;This tag allows you to document information about the parameters to a function, method or class (constructor)&lt;br /&gt;&lt;div style="color: orange;"&gt;@public&lt;/div&gt;This tag allows you to document public methods or variables.&lt;br /&gt;&lt;div style="color: orange;"&gt;@private&lt;/div&gt;This tag allows you to document private methods or variables.&lt;br /&gt;&lt;div style="color: orange;"&gt;@type&lt;/div&gt;This tag allows you to document the type of value a variable refers to, or the type of value returned by a function.&lt;br /&gt;&lt;div style="color: orange;"&gt;@returns&lt;/div&gt;This tag documents the value returned by a function or method. You can specify a type of the returned value in curly braces {...}.&lt;br /&gt;&lt;div style="color: orange;"&gt;@link&lt;/div&gt;This tag allows you to create a HTML link to some other documented symbol (similar link in JavaDoc).&lt;br /&gt;&lt;br /&gt;Let's document the JavaScript code! I have a class called &lt;span style="color: orange;"&gt;WhiteboardDesigner&lt;/span&gt; which expects 5 parameters (to be passed to constructor) and has many public / private methods. The documented class looks like&lt;br /&gt;&lt;pre class="brush:js"&gt;/**&lt;br /&gt;* @fileOverview&lt;br /&gt;* @author &amp;lt;a href="mailto:ovaraksin@googlemail.com"&amp;gt;Oleg Varaksin&amp;lt;/a&amp;gt;&lt;br /&gt;* @version 0.2&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Whiteboard designer class for element drawing.&lt;br /&gt;* @class&lt;br /&gt;* @param witeboardConfig whiteboard's configuration {@link WhiteboardConfig}&lt;br /&gt;* @param whiteboardId whiteboard's id&lt;br /&gt;* @param user user (user name) working with this whiteboard&lt;br /&gt;* @param pubSubUrl URL for bidirectional communication&lt;br /&gt;* @param pubSubTransport transport protocol "long-polling" | "streaming" | "websocket"&lt;br /&gt;*/&lt;br /&gt;WhiteboardDesigner = function(witeboardConfig, whiteboardId, user, pubSubUrl, pubSubTransport) {&lt;br /&gt;    /**&lt;br /&gt;     * Whiteboard's configuration {@link WhiteboardConfig}.&lt;br /&gt;     * @public&lt;br /&gt;     * @type WhiteboardConfig&lt;br /&gt;     */&lt;br /&gt;    this.config = witeboardConfig;&lt;br /&gt;    /**&lt;br /&gt;     * Whiteboard's id.&lt;br /&gt;     * @public&lt;br /&gt;     * @type uuid&lt;br /&gt;     */    &lt;br /&gt;    this.whiteboardId = whiteboardId;&lt;br /&gt;    /**&lt;br /&gt;     * User which works with this whiteboard.&lt;br /&gt;     * @public&lt;br /&gt;     * @type string&lt;br /&gt;     */    &lt;br /&gt;    this.user = user;&lt;br /&gt;    /**&lt;br /&gt;     * URL for bidirectional communication.&lt;br /&gt;     * @public&lt;br /&gt;     * @type string&lt;br /&gt;     */    &lt;br /&gt;    this.pubSubUrl = pubSubUrl;&lt;br /&gt;    /**&lt;br /&gt;     * Transport protocol "long-polling" | "streaming" | "websocket".&lt;br /&gt;     * @public&lt;br /&gt;     * @type string&lt;br /&gt;     */    &lt;br /&gt;    this.pubSubTransport = pubSubTransport;&lt;br /&gt;    /**&lt;br /&gt;     * Logging flag, true - logging is visible, false - otherwise.&lt;br /&gt;     * @public&lt;br /&gt;     * @type boolean&lt;br /&gt;     */    &lt;br /&gt;    this.logging = false;&lt;br /&gt;    /**&lt;br /&gt;     * Raphael's canvas.&lt;br /&gt;     * @private&lt;br /&gt;     * @type Raphael's paper&lt;br /&gt;     */    &lt;br /&gt;    var paper = Raphael(this.config.ids.whiteboard, whiteboard.width(), whiteboard.height());&lt;br /&gt;    &lt;br /&gt;    ...&lt;br /&gt;    &lt;br /&gt;    /** Draws image with default properties.&lt;br /&gt;    * @public&lt;br /&gt;    * @param inputUrl image URL.&lt;br /&gt;    * @param width image width.&lt;br /&gt;    * @param height image height.&lt;br /&gt;    */    &lt;br /&gt;    this.drawImage = function(inputUrl, width, height) {&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /** Gets currently selected whiteboard element.&lt;br /&gt;    * @public&lt;br /&gt;    * @returns {Raphael's element} currently selected element&lt;br /&gt;    */&lt;br /&gt;    this.getSelectedObject = function() {&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;    /** Outputs debug messages.&lt;br /&gt;    * @private&lt;br /&gt;    * @param msg message&lt;br /&gt;    */&lt;br /&gt;    var logDebug = function(msg) {&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;How to generate a documentation now? I would like to show a quick and simple way. Download &lt;a href="http://code.google.com/p/jsdoc-toolkit/downloads/list"&gt;JsDoc Toolkit zip file&lt;/a&gt; at first. Extract it and go to the directory &lt;span style="color: orange;"&gt;jsdoc-toolkit&lt;/span&gt;. Create there a new folder with any name which will contain your documented JavaScript files. I have created a folder called "&lt;span style="color: orange;"&gt;whiteboard&lt;/span&gt;". Copy all JavaScript files into this folder. Open a DOS console or Linux terminal or whatever at &lt;span style="color: orange;"&gt;jsdoc-toolkit&lt;/span&gt; and type&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;nbsp;&lt;br /&gt;java -jar jsrun.jar app/run.js -a -p -t=templates/jsdoc ./&amp;lt;yours folder name&amp;gt;/*.*&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;In my case it's&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;nbsp;&lt;br /&gt;java -jar jsrun.jar app/run.js -a -p -t=templates/jsdoc ./whiteboard/*.*&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;JsDoc Toolkit runs via the Mozilla JavaScript Engine "Rhino." Rhino is wrapped in a runner application called &lt;span style="color: orange;"&gt;jsrun&lt;/span&gt;. Option &lt;span style="color: orange;"&gt;-a&lt;/span&gt; says: include all functions, even undocumented ones. Option &lt;span style="color: orange;"&gt;-p&lt;/span&gt; says: include symbols tagged as private, underscored and inner symbols (such symbols are not included per default). Option &lt;span style="color: orange;"&gt;-t&lt;/span&gt; is required und used to point to templates for output formatting. Using of default build-in templates which are located under &lt;span style="color: orange;"&gt;templates/jsdoc&lt;/span&gt; is satisfying in most cases.&lt;br /&gt;&lt;br /&gt;After script running you will find generated files in the &lt;span style="color: orange;"&gt;out&lt;/span&gt; folder. Entry file is &lt;span style="color: orange;"&gt;index.html&lt;/span&gt;. Its location is &lt;span style="color: orange;"&gt;.../jsdoc-toolkit/out/index.html&lt;/span&gt; You can see &lt;a href="http://fractalsoft.de/uni/jsdoc/index.html"&gt;online here&lt;/a&gt; how does it look for my project. Have much fun!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-2003147301065306697?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/2003147301065306697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/09/quick-practical-introduction-to-jsdoc.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2003147301065306697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2003147301065306697'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/09/quick-practical-introduction-to-jsdoc.html' title='Quick practical introduction to JSDoc (JsDoc Toolkit)'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-7021913790967294533</id><published>2011-09-16T01:20:00.000-07:00</published><updated>2011-09-21T00:40:41.179-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Inheritance in Maven based web projects</title><content type='html'>Sometimes you want to define a base web project and reuse all web based stuff in all other web projects. This is not rare in big projects. The first thought coming in mind is inheritance. Is there any inheritance between web projects at all? Yes, in a manner of speaking. In Maven based projects there is a nice "&lt;span style="color: orange;"&gt;overlay&lt;/span&gt;" feature for &lt;span style="color: orange;"&gt;maven-war-plugin&lt;/span&gt;. You can point to the base WAR project in the &lt;span style="color: orange;"&gt;overlay&lt;/span&gt; tag and the base project gets extracted bevor it's stuff will be extended or overwritten by inherited project. An example:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;plugin&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;    &amp;lt;configuration&amp;gt;&lt;br /&gt;        &amp;lt;overlays&amp;gt;&lt;br /&gt;            &amp;lt;overlay&amp;gt;&lt;br /&gt;                &amp;lt;groupId&amp;gt;ip.client&amp;lt;/groupId&amp;gt;&lt;br /&gt;                &amp;lt;artifactId&amp;gt;ip-theme-framework&amp;lt;/artifactId&amp;gt;&lt;br /&gt;                &amp;lt;classifier&amp;gt;webapp&amp;lt;/classifier&amp;gt;&lt;br /&gt;                &amp;lt;excludes&amp;gt;&lt;br /&gt;                    &amp;lt;exclude&amp;gt;META-INF/**&amp;lt;/exclude&amp;gt;&lt;br /&gt;                    &amp;lt;exclude&amp;gt;WEB-INF/web.xml&amp;lt;/exclude&amp;gt;&lt;br /&gt;                    &amp;lt;exclude&amp;gt;WEB-INF/lib/**&amp;lt;/exclude&amp;gt;&lt;br /&gt;                    &amp;lt;exclude&amp;gt;WEB-INF/classes/**&amp;lt;/exclude&amp;gt;&lt;br /&gt;                &amp;lt;/excludes&amp;gt;&lt;br /&gt;            &amp;lt;/overlay&amp;gt;&lt;br /&gt;        &amp;lt;/overlays&amp;gt;&lt;br /&gt;    &amp;lt;/configuration&amp;gt;&lt;br /&gt;&amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;/pre&gt;You have also to add a dependency in your inherited project for the base project, of course. Well, this feature works fine, but there is a problem with transitive dependencies. Dependencies defined in the base project are "invisible" for inherited projects. You can not use transitive dependencies, they aren't going to be inherited. And adding of all dependencies again in inherited projects is error-prone and causes some issues during release management. To solve this problem, we can set packaging of all web projects as &lt;span style="color: orange;"&gt;jar&lt;/span&gt;. That's what we do in my company.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;packaging&amp;gt;jar&amp;lt;/packaging&amp;gt;&lt;br /&gt;&lt;/pre&gt;With packaging &lt;span style="color: orange;"&gt;jar&lt;/span&gt; you have still a WAR archive at the end, but Java sources are packed to one jar file which is placed by Maven below &lt;span style="color: orange;"&gt;WEB-INF/lib&lt;/span&gt; inside of the WAR. &lt;span style="color: orange;"&gt;WEB-INF/classes&lt;/span&gt; stays empty. Dependencies get now accepted. One thing to keep in mind: WAR projects with packaging &lt;span style="color: orange;"&gt;jar&lt;/span&gt; should be specified twice as dependencies. Once without &lt;span style="color: orange;"&gt;&amp;lt;type&amp;gt;&lt;/span&gt; and once with &lt;span style="color: orange;"&gt;&amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;&lt;/span&gt;. An example:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;ip.client&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;ip-theme-framework&amp;lt;/artifactId&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;ip.client&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;ip-theme-framework&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;classifier&amp;gt;webapp&amp;lt;/classifier&amp;gt;&lt;br /&gt;    &amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;&lt;br /&gt;    &amp;lt;scope&amp;gt;runtime&amp;lt;/scope&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;/pre&gt;The last be not least is the support in IDEs. JAR projects are not recognized as web projects in Eclipse, IntelliJ or somewhere else and you lose all goodies from your preferred IDE. A solution is simple and uses profiles. Define a property &lt;span style="color: orange;"&gt;${packaging.war}&lt;/span&gt; for a special profile (see my last post).&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;profile&amp;gt;&lt;br /&gt;    &amp;lt;id&amp;gt;ide&amp;lt;/id&amp;gt;&lt;br /&gt;    &amp;lt;properties&amp;gt;&lt;br /&gt;        &amp;lt;packaging.war&amp;gt;war&amp;lt;/packaging.war&amp;gt;&lt;br /&gt;    &amp;lt;/properties&amp;gt;&lt;br /&gt;&amp;lt;/profile&amp;gt;&lt;br /&gt;&lt;/pre&gt;write variable &lt;span style="color: orange;"&gt;packaging.war&lt;/span&gt; in the packaging tag of your project&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;packaging&amp;gt;${packaging.war}&amp;lt;/packaging&amp;gt;&lt;br /&gt;&lt;/pre&gt;and let Maven run with this profile when creating IDE specific files:&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn -Pide eclipse:eclipse&lt;br /&gt;mvn -Pide idea:idea&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;u&gt;Summary:&lt;/u&gt; Overlays help to reuse web projects. They also help to customize web projects by having one big core project and many small custom specific projects which only have specific CSS, Images (logos, ect.) and messages in property files. Custom specific Maven projects don't have Java classes - the aim is to overwrite / extend resources of core project and achieve a custom Look-&amp;amp;-Feel.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-7021913790967294533?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/7021913790967294533/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/09/inheritance-in-maven-based-web-projects.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7021913790967294533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7021913790967294533'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/09/inheritance-in-maven-based-web-projects.html' title='Inheritance in Maven based web projects'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-2462881473742662973</id><published>2011-09-14T11:39:00.000-07:00</published><updated>2011-10-05T02:12:12.988-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Filter web.xml with Maven</title><content type='html'>&lt;a href="http://maven.apache.org/"&gt;Maven&lt;/a&gt; (build manager for Java projects) has a feature called "&lt;span style="color: orange;"&gt;filtering&lt;/span&gt;". As is generally known you can replace with Maven any variables defined with placeholders like &lt;span style="color: orange;"&gt;${my.variable}&lt;/span&gt;. Such variables can be placed in property files or any other resource files like CSS, JavaScript, (X)HTML. I normally place placeholders in &lt;span style="color: orange;"&gt;web.xml&lt;/span&gt; and replace them by real values while Maven runs with a certain profile. My default Maven profile is e.g. "&lt;span style="color: orange;"&gt;development&lt;/span&gt;". Another profile is "&lt;span style="color: orange;"&gt;release&lt;/span&gt;". To build artefacts with "&lt;span style="color: orange;"&gt;release&lt;/span&gt;" profile I run&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn -Prelease clean install&lt;/pre&gt;Option &lt;span style="color: orange;"&gt;-P&lt;/span&gt; is for profile you want to build software with. How to set up filtering of &lt;span style="color: orange;"&gt;web.xml&lt;/span&gt; exactly? At first we need to create a directory "&lt;span style="color: orange;"&gt;filter&lt;/span&gt;" under "&lt;span style="color: orange;"&gt;src/main&lt;/span&gt;" and place two (or more) property files under "&lt;span style="color: orange;"&gt;src/main/filter&lt;/span&gt;". In order to demonstrate filtering for two profiles I'm going to create &lt;span style="color: orange;"&gt;development.properties&lt;/span&gt; and &lt;span style="color: orange;"&gt;release.properties&lt;/span&gt;. So, our structure looks now as follows:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-JrCzkpKOV78/TnDxz-5-r9I/AAAAAAAAAFk/_JY30FJC8f4/s1600/filterWeb.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-JrCzkpKOV78/TnDxz-5-r9I/AAAAAAAAAFk/_JY30FJC8f4/s1600/filterWeb.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Let us define the content of &lt;span style="color: orange;"&gt;development.properties&lt;/span&gt; as&lt;br /&gt;&lt;pre class="brush:xml"&gt;jsf.faceletsRefreshPeriod=2&lt;br /&gt;jsf.resourceUpdateCheckPeriod=2&lt;br /&gt;&lt;/pre&gt;and the content of &lt;span style="color: orange;"&gt;release.properties&lt;/span&gt; as&lt;br /&gt;&lt;pre class="brush:xml"&gt;jsf.faceletsRefreshPeriod=-1&lt;br /&gt;jsf.resourceUpdateCheckPeriod=-1&lt;br /&gt;&lt;/pre&gt;The next step is to modify &lt;span style="color: orange;"&gt;web.xml&lt;/span&gt;. &lt;span style="color: orange;"&gt;web.xml&lt;/span&gt; gets two placeholders:&lt;br /&gt;&lt;pre class="brush:xml"&gt;...&lt;br /&gt;&amp;lt;context-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;javax.faces.FACELETS_REFRESH_PERIOD&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;${jsf.faceletsRefreshPeriod}&amp;lt;/param-value&amp;gt;&lt;br /&gt;&amp;lt;/context-param&amp;gt;&lt;br /&gt;&amp;lt;context-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;com.sun.faces.resourceUpdateCheckPeriod&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;${jsf.resourceUpdateCheckPeriod}&amp;lt;/param-value&amp;gt;&lt;br /&gt;&amp;lt;/context-param&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;The last step is to modify &lt;span style="color: orange;"&gt;pom.xml&lt;/span&gt;. Actually we don't need two profiles. Let us only define the "&lt;span style="color: orange;"&gt;release&lt;/span&gt;" profile and assume default case without any profiles as "&lt;span style="color: orange;"&gt;development&lt;/span&gt;".&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;profiles&amp;gt;&lt;br /&gt;    &amp;lt;profile&amp;gt;&lt;br /&gt;        &amp;lt;id&amp;gt;release&amp;lt;/id&amp;gt;&lt;br /&gt;        &amp;lt;properties&amp;gt;&lt;br /&gt;            &amp;lt;webapp.filter&amp;gt;release&amp;lt;/webapp.filter&amp;gt;&lt;br /&gt;        &amp;lt;/properties&amp;gt;&lt;br /&gt;    &amp;lt;/profile&amp;gt;&lt;br /&gt;&amp;lt;/profiles&amp;gt;&lt;br /&gt;&lt;/pre&gt;Important thing is to define a property "&lt;span style="color: orange;"&gt;webapp.filter&lt;/span&gt;" for "&lt;span style="color: orange;"&gt;release&lt;/span&gt;" profile. For default case we have also to add this line to &lt;span style="color: orange;"&gt;pom.xml&lt;/span&gt; (somewhere at the end):&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;properties&amp;gt;&lt;br /&gt;    &amp;lt;webapp.filter&amp;gt;development&amp;lt;/webapp.filter&amp;gt;&lt;br /&gt;&amp;lt;/properties&amp;gt;&lt;br /&gt;&lt;/pre&gt;To make it working together with maven-war plugin (in this case) we need to activate filtering feature. That means, before WAR archive gets packed, placeholders in &lt;span style="color: orange;"&gt;web.xml&lt;/span&gt; should be already replaced by real values from property files. This task is simple:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;plugin&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;executions&amp;gt;&lt;br /&gt;        &amp;lt;execution&amp;gt;&lt;br /&gt;            &amp;lt;id&amp;gt;war&amp;lt;/id&amp;gt;&lt;br /&gt;            &amp;lt;phase&amp;gt;package&amp;lt;/phase&amp;gt;&lt;br /&gt;            &amp;lt;goals&amp;gt;&lt;br /&gt;                &amp;lt;goal&amp;gt;war&amp;lt;/goal&amp;gt;&lt;br /&gt;            &amp;lt;/goals&amp;gt;&lt;br /&gt;            &amp;lt;configuration&amp;gt;&lt;br /&gt;                ...&lt;br /&gt;                &amp;lt;filteringDeploymentDescriptors&amp;gt;true&amp;lt;/filteringDeploymentDescriptors&amp;gt;&lt;br /&gt;                &amp;lt;filters&amp;gt;&lt;br /&gt;                    &amp;lt;filter&amp;gt;${basedir}/src/main/filter/${webapp.filter}.properties&amp;lt;/filter&amp;gt;&lt;br /&gt;                &amp;lt;/filters&amp;gt;&lt;br /&gt;            &amp;lt;/configuration&amp;gt;&lt;br /&gt;        &amp;lt;/execution&amp;gt;&lt;br /&gt;    &amp;lt;/executions&amp;gt;&lt;br /&gt;&amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;/pre&gt;We leverages here the variable &lt;span style="color: orange;"&gt;${webapp.filter}&lt;/span&gt; which points to file name depends on currently active profile. That's all. You can now run builds with&lt;br /&gt;&lt;pre class="brush:xml"&gt;// build for development&lt;br /&gt;mvn clean install&lt;br /&gt;&lt;br /&gt;// build for release&lt;br /&gt;mvn -Prelease clean install&lt;br /&gt;&lt;/pre&gt;There is only one issue when using Jetty Maven plugin and let it runs with&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn jetty:run&lt;br /&gt;&lt;/pre&gt;Jetty looks as default under source directory and scans &lt;span style="color: orange;"&gt;src/main/webapp/WEB-INF/web.xml&lt;/span&gt;. But located there &lt;span style="color: orange;"&gt;web.xml&lt;/span&gt; has placeholders. How to solve that? A solution is easy. This is a bonus part of this post. We can leverages &lt;span style="color: orange;"&gt;overrideDescriptor&lt;/span&gt; tag and specify a XML file with our own parts of &lt;span style="color: orange;"&gt;web.xml&lt;/span&gt; which overwrite the same parts in &lt;span style="color: orange;"&gt;src/main/webapp/WEB-INF/web.xml&lt;/span&gt; when Jetty running.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;plugin&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;org.mortbay.jetty&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;maven-jetty-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;configuration&amp;gt;&lt;br /&gt;        &amp;lt;webAppConfig&amp;gt;&lt;br /&gt;            ...&lt;br /&gt;            &amp;lt;overrideDescriptor&amp;gt;src/main/resources/overrideweb.xml&amp;lt;/overrideDescriptor&amp;gt;&lt;br /&gt;        &amp;lt;/webAppConfig&amp;gt;&lt;br /&gt;    &amp;lt;/configuration&amp;gt;&lt;br /&gt;&amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;/pre&gt;The content of &lt;span style="color: orange;"&gt;overrideweb.xml&lt;/span&gt; is (we normally need settings for default "&lt;span style="color: orange;"&gt;development&lt;/span&gt;" profile when Jetty running) &lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;web-app version="2.5"&lt;br /&gt;         xmlns="http://java.sun.com/xml/ns/javaee"&lt;br /&gt;         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;context-param&amp;gt;&lt;br /&gt;        &amp;lt;param-name&amp;gt;javax.faces.FACELETS_REFRESH_PERIOD&amp;lt;/param-name&amp;gt;&lt;br /&gt;        &amp;lt;param-value&amp;gt;2&amp;lt;/param-value&amp;gt;&lt;br /&gt;    &amp;lt;/context-param&amp;gt;&lt;br /&gt;    &amp;lt;context-param&amp;gt;&lt;br /&gt;        &amp;lt;param-name&amp;gt;com.sun.faces.resourceUpdateCheckPeriod&amp;lt;/param-name&amp;gt;&lt;br /&gt;        &amp;lt;param-value&amp;gt;2&amp;lt;/param-value&amp;gt;&lt;br /&gt;    &amp;lt;/context-param&amp;gt;&lt;br /&gt;    &amp;lt;context-param&amp;gt;&lt;br /&gt;        &amp;lt;param-name&amp;gt;com.sun.faces.injectionProvider&amp;lt;/param-name&amp;gt;&lt;br /&gt;        &amp;lt;param-value&amp;gt;com.sun.faces.vendor.WebContainerInjectionProvider&amp;lt;/param-value&amp;gt;&lt;br /&gt;    &amp;lt;/context-param&amp;gt;&lt;br /&gt;    &amp;lt;context-param&amp;gt;&lt;br /&gt;        &amp;lt;param-name&amp;gt;com.sun.faces.spi.AnnotationProvider&amp;lt;/param-name&amp;gt;&lt;br /&gt;        &amp;lt;param-value&amp;gt;com.sun.faces.config.AnnotationScanner&amp;lt;/param-value&amp;gt;&lt;br /&gt;    &amp;lt;/context-param&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;listener&amp;gt;&lt;br /&gt;        &amp;lt;listener-class&amp;gt;com.sun.faces.config.ConfigureListener&amp;lt;/listener-class&amp;gt;&lt;br /&gt;    &amp;lt;/listener&amp;gt;&lt;br /&gt;&amp;lt;/web-app&amp;gt;&lt;br /&gt;&lt;/pre&gt;Happy filtering!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-2462881473742662973?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/2462881473742662973/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/09/filter-webxml-with-maven.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2462881473742662973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2462881473742662973'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/09/filter-webxml-with-maven.html' title='Filter web.xml with Maven'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-JrCzkpKOV78/TnDxz-5-r9I/AAAAAAAAAFk/_JY30FJC8f4/s72-c/filterWeb.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-2483754125652000463</id><published>2011-09-07T04:10:00.001-07:00</published><updated>2011-12-29T04:03:03.328-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Useful Maven commandos</title><content type='html'>Everybody who uses &lt;a href="http://maven.apache.org/"&gt;Maven&lt;/a&gt; from console / terminal knows how sometimes difficult to remember all handy commandos using in day job. A small reference list should help.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Skip running tests for a particular project.&lt;/i&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn clean install -Dmaven.test.skip=true&lt;br /&gt;&lt;/pre&gt;&lt;i&gt;Continue build if it has been failed at certain point.&lt;/i&gt; Maybe you have many sub-projects and build your entire project from top to down. "-rf" parameters allow to continue maven running where you want after any build errors. Assume my current top directory where I let Maven run is D:\SVN and the build was broken at D:\SVN\eIP\CoreServer\DatastoreConnector. Following command let go on with the build and skip this not compilable or not testable sub-project. &lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn clean install -rf eIP\CoreServer\DatastoreConnector&lt;br /&gt;&lt;/pre&gt;&lt;i&gt;Get source jar files (e.g. for Eclipse projects).&lt;/i&gt; Having source files in local repository allow to jump into this directly from your preferred IDE.&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn eclipse:eclipse -DdownloadSources=true&lt;br /&gt;&lt;/pre&gt;or run&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn dependency:sources&lt;br /&gt;&lt;/pre&gt;to download all source jars for a given project into local repository. The same for JavaDoc (if it's available).&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn eclipse:eclipse -DdownloadJavadocs=true&lt;br /&gt;&lt;/pre&gt;&lt;i&gt;Output project's dependency tree.&lt;/i&gt; I like that! You can see versions of all used artefacts.&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn dependency:tree&lt;br /&gt;&lt;/pre&gt;Output is like this one&lt;br /&gt;&lt;pre class="brush:xml"&gt;[INFO] ip.client:ip-jsftoolkit:jar:3.4.1-SNAPSHOT&lt;br /&gt;[INFO] +- ip.client:ip-filter-security:jar:3.4.0:compile&lt;br /&gt;[INFO] |  +- com.scalaris.commons:scalaris-commons-enterprise:jar:2.3.1-SNAPSHOT:compile&lt;br /&gt;[INFO] |  |  +- com.scalaris.commons:scalaris-commons-lang:jar:2.3.0:compile&lt;br /&gt;[INFO] |  |  +- org.apache.commons:commons-lang3:jar:3.0:compile&lt;br /&gt;[INFO] |  |  \- commons-lang:commons-lang:jar:2.6:compile&lt;br /&gt;[INFO] |  +- ip.client:ip-client-commons:jar:3.4.0:compile&lt;br /&gt;[INFO] |  |  +- ip.services:ip-core-services:jar:3.4.0:compile&lt;br /&gt;[INFO] |  |  |  \- ip.datatransfer:ip-datatransfer-commons:jar:3.4.0:compile&lt;br /&gt;..................................................&lt;br /&gt;[INFO] |  +- commons-httpclient:commons-httpclient:jar:3.0.1:compile&lt;br /&gt;[INFO] |  +- org.apache.commons:commons-jexl:jar:2.0:compile&lt;br /&gt;[INFO] |  \- joda-time:joda-time:jar:1.6.2:compile&lt;br /&gt;[INFO] +- javax.ejb:ejb:jar:3.0:provided&lt;br /&gt;[INFO] +- javax.servlet:servlet-api:jar:2.5:provided&lt;br /&gt;[INFO] \- com.scalaris.commons:scalaris-commons-test:jar:2.2.8-SNAPSHOT:test&lt;br /&gt;[INFO]    +- jmock:jmock:jar:1.2.0:test&lt;br /&gt;[INFO]    +- junit:junit:jar:3.8.2:test&lt;br /&gt;&lt;/pre&gt;&lt;i&gt;Filter project's dependency tree in order to see only a specified dependency.&lt;/i&gt; The syntax for filter patterns is as follows: [groupId]:[artifactId]:[type]:[version]&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn dependency:tree -Dincludes=com.sun.faces:jsf-impl&lt;br /&gt;&lt;/pre&gt;&lt;i&gt;Display the effective pom of a project. &lt;/i&gt;The effective pom represents the current pom state for a project (incl. maven super pom and active profiles).&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn help:effective-pom&lt;br /&gt;&lt;/pre&gt;&lt;i&gt;Generate files needed for an IntelliJ IDEA project setup.&lt;/i&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn idea:idea&lt;br /&gt;&lt;/pre&gt;This plugin has no way to determine the name of the JDK you are using. It uses by default the same JDK as output java -version. Using with defined JDK:&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn idea:idea -DjdkName=1.5&lt;br /&gt;&lt;/pre&gt;&lt;i&gt;Create a web project from scratch.&lt;/i&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn archetype:create &lt;br /&gt; -DarchetypeGroupId=org.apache.maven.archetypes &lt;br /&gt; -DarchetypeArtifactId=maven-archetype-webapp &lt;br /&gt; -DarchetypeVersion=1.0 &lt;br /&gt; -DgroupId=com.maventest &lt;br /&gt; -DartifactId=mywebtest &lt;br /&gt; -Dversion=1.0-SNAPSHOT&lt;/pre&gt;&lt;i&gt;Deploy artefact in global repository&lt;/i&gt; (located e.g. in file://///xyz.abc.com/maven/repo-m2).&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn deploy:deploy-file&lt;br /&gt; -DgroupId=com.maventest&lt;br /&gt; -DartifactId=mywebtest&lt;br /&gt; -Dversion=1.0-SNAPSHOT&lt;br /&gt; -Dpackaging=war&lt;br /&gt; -Dfile=mywebapp.jar&lt;br /&gt; -DrepositoryId=xyz-release &lt;br /&gt; -Durl=file://///xyz.abc.com/maven/repo-m2&lt;/pre&gt;&lt;i&gt;Check all the dependencies used in your project and display a list of those dependencies with newer versions available.&lt;/i&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn versions:display-dependency-updates&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;[INFO] The following dependency updates are available:&lt;br /&gt;[INFO]   org.apache.maven:maven-artifact ........................ 2.0 -&gt; 2.0.9&lt;br /&gt;[INFO]   org.apache.maven:maven-plugin-api ...................... 2.0 -&gt; 2.0.9&lt;br /&gt;[INFO]   org.apache.maven:maven-project ....................... 2.0.2 -&gt; 2.0.9&lt;br /&gt;[INFO]   org.codehaus.plexus:plexus-utils ....................... 1.1 -&gt; 1.5.6&lt;br /&gt;&lt;/pre&gt;&lt;i&gt;Check all the plugins and reports used in your project and display a list of those plugins with newer versions available.&lt;/i&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;mvn versions:display-plugin-updates&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;[INFO] The following plugin updates are available:&lt;br /&gt;[INFO]   maven-deploy-plugin ...................................... 2.5 -&gt; 2.7&lt;br /&gt;[INFO]   maven-jar-plugin ..................................... 2.3.1 -&gt; 2.3.2&lt;br /&gt;[INFO]   maven-plugin-plugin ...................................... 2.7 -&gt; 2.9&lt;br /&gt;[INFO]   maven-resources-plugin ................................. 2.4.3 -&gt; 2.5&lt;br /&gt;&lt;/pre&gt;&lt;i&gt;Decompile Java classes in the maven central repository&lt;/i&gt; :-). Useful if source code isn't available. &lt;a href="http://www.avajava.com/tutorials/lessons/how-do-i-decompile-java-classes-in-the-maven-central-repository.html"&gt;The trick is here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-2483754125652000463?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/2483754125652000463/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/09/useful-maven-commandos.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2483754125652000463'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2483754125652000463'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/09/useful-maven-commandos.html' title='Useful Maven commandos'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-416618731653400964</id><published>2011-08-25T14:47:00.000-07:00</published><updated>2011-08-27T02:12:18.365-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>Combine jQuery Datepicker and Spinner for fast day incrementation / decrementation</title><content type='html'>Is it possible to add + / - buttons to &lt;a href="http://jqueryui.com/demos/datepicker/"&gt;jQuery UI Datepicker&lt;/a&gt; in order to increment / decrement days in a comfortable way? Yes, it's possible. I have done this task - see screenshot.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-9GJEjN04Mtc/Tla-XVJJdVI/AAAAAAAAAFY/hD3h8MLPW8A/s1600/dateSpinner.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-9GJEjN04Mtc/Tla-XVJJdVI/AAAAAAAAAFY/hD3h8MLPW8A/s1600/dateSpinner.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;This is an extended &lt;a href="http://www.primefaces.org/showcase/ui/calendarBasic.jsf"&gt;PrimeFaces Calendar&lt;/a&gt; with added "&lt;span style="color: orange;"&gt;dateSpinner&lt;/span&gt;" mode. I would like to omit JSF part and only show HTML / CSS / JavaScript part of such combined calendar. All what you need is to wrap the datepicker markup with a span element, add themable up / down arrows and use datepicker utility functions &lt;a href="http://docs.jquery.com/UI/Datepicker/formatDate"&gt;$.datepicker.formatDate(format, date, settings)&lt;/a&gt; and &lt;a href="http://docs.jquery.com/UI/Datepicker/parseDate"&gt;$.datepicker.parseDate(format, value, settings)&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;HTML&lt;/b&gt;&lt;br /&gt;Original HTML with a calendar icon (called &lt;i&gt;icon trigger&lt;/i&gt; in jQuery Datepicker) looks very simple&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;input id="datepicker" class="hasDatepicker" type="text"&amp;gt;&lt;br /&gt;&amp;lt;img class="ui-datepicker-trigger" src="images/calendar.gif" alt="..." title="..."&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;You have to extend this as follows&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;lt;span id="datepickerWrapper" class="ui-ccalendar ui-widget ui-corner-all"&amp;gt;&lt;br /&gt;	&amp;lt;input id="datepicker" class="hasDatepicker" type="text"&amp;gt;&lt;br /&gt;	&amp;lt;img class="ui-datepicker-trigger" src="images/calendar.gif" alt="..." title="..."&amp;gt;&lt;br /&gt;	&amp;lt;a class="ui-ccalendar-button ui-ccalendar-up ui-corner-tr ui-button ui-widget ui-state-default ui-button-text-only"&amp;gt;&lt;br /&gt;		&amp;lt;span class="ui-button-text"&amp;gt;&lt;br /&gt;			&amp;lt;span class="ui-icon ui-icon-triangle-1-n"&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;		&amp;lt;/span&amp;gt;&lt;br /&gt;	&amp;lt;/a&amp;gt;&lt;br /&gt;	&amp;lt;a class="ui-ccalendar-button ui-ccalendar-down ui-corner-br ui-button ui-widget ui-state-default ui-button-text-only"&amp;gt;&lt;br /&gt;		&amp;lt;span class="ui-button-text"&amp;gt;&lt;br /&gt;			&amp;lt;span class="ui-icon ui-icon-triangle-1-s"&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;		&amp;lt;/span&amp;gt;&lt;br /&gt;	&amp;lt;/a&amp;gt;&lt;br /&gt;&amp;lt;/span&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;CSS&lt;/b&gt;&lt;br /&gt;The most CSS classes above are jQuery UI classes. I marked own classes with &lt;span style="color: orange;"&gt;ui-ccalendar&lt;/span&gt;. In the CSS part is very important to shift spinner's arrow buttons to left. I have shifted absolute positioned buttons with CSS statement &lt;span style="color: orange;"&gt;right: 17px;&lt;/span&gt;. We achieve with this displacement that the calendar icon is visible.&lt;br /&gt;&lt;pre class="brush:css"&gt;.ui-ccalendar {&lt;br /&gt;    display: inline-block;&lt;br /&gt;    overflow: visible;&lt;br /&gt;    padding: 0;&lt;br /&gt;    position: relative;&lt;br /&gt;    vertical-align: middle;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.ui-ccalendar-button {&lt;br /&gt;    cursor: default;&lt;br /&gt;    display: block;&lt;br /&gt;    font-size: 0.5em;&lt;br /&gt;    height: 50%;&lt;br /&gt;    margin: 0;&lt;br /&gt;    overflow: hidden;&lt;br /&gt;    padding: 0;&lt;br /&gt;    position: absolute;&lt;br /&gt;    right: 17px;&lt;br /&gt;    text-align: center;&lt;br /&gt;    vertical-align: middle;&lt;br /&gt;    width: 16px;&lt;br /&gt;    z-index: 100;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.ui-ccalendar .ui-icon {&lt;br /&gt;    left: 0;&lt;br /&gt;    margin-top: -8px;&lt;br /&gt;    position: absolute;&lt;br /&gt;    top: 50%;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.ui-ccalendar-up {&lt;br /&gt;    top: 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.ui-ccalendar-down {&lt;br /&gt;    bottom: 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.ui-ccalendar .ui-icon-triangle-1-s {&lt;br /&gt;    background-position: -65px -16px;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.ui-ccalendar .ui-icon-triangle-1-n {&lt;br /&gt;    margin-top: -9px;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;JavaScript&lt;/b&gt;&lt;br /&gt;In this part I use the mentioned above utility functions &lt;span style="color: orange;"&gt;formatDate()&lt;/span&gt; / &lt;span style="color: orange;"&gt;parseDate() &lt;/span&gt;and &lt;span style="color: orange;"&gt;setDate()&lt;/span&gt; / &lt;span style="color: orange;"&gt;getDate()&lt;/span&gt; API of &lt;span style="color: orange;"&gt;Date&lt;/span&gt; object to increment / decrement a single day. Month and year boundaries are considered automatically and in- / decremented if necessary. In- / decrementation logic is bound to mousedown event on spinner buttons.&lt;br /&gt;&lt;pre class="brush:js"&gt;var datepickerInput = $('#datepicker');&lt;br /&gt;datepickerInput.datepicker({dateFormat: 'yy-mm-dd', ... other configuration if needed ...});&lt;br /&gt;&lt;br /&gt;$('#datepickerWrapper').children('.ui-ccalendar-button').mouseover(function() {&lt;br /&gt;	$(this).addClass('ui-state-hover');&lt;br /&gt;}).mouseout(function() {&lt;br /&gt;	$(this).removeClass('ui-state-hover');&lt;br /&gt;}).mouseup(function() {&lt;br /&gt;	$(this).removeClass('ui-state-active');&lt;br /&gt;}).mousedown(function() {&lt;br /&gt;	var el = $(this);&lt;br /&gt;	el.addClass('ui-state-active');&lt;br /&gt;	try {&lt;br /&gt;		// get configured date format&lt;br /&gt;		var dateFormat = datepickerInput.datepicker("option", "dateFormat");&lt;br /&gt;&lt;br /&gt;		// extract a date from a string value with a specified format&lt;br /&gt;		var date = $.datepicker.parseDate(dateFormat, datepickerInput.val());&lt;br /&gt;		if (el.hasClass('ui-ccalendar-up')) {&lt;br /&gt;			// increment day&lt;br /&gt;			date.setDate(date.getDate() + 1);&lt;br /&gt;		} else {&lt;br /&gt;			// decrement day&lt;br /&gt;			date.setDate(date.getDate() - 1);&lt;br /&gt;		}&lt;br /&gt;&lt;br /&gt;		// format a date into a string value with a specified format&lt;br /&gt;		var strDate = $.datepicker.formatDate(dateFormat, date);&lt;br /&gt;		datepickerInput.val(strDate);&lt;br /&gt;	} catch (err) {&lt;br /&gt;		// ignore and nothing to do&lt;br /&gt;	}&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;Important is here "&lt;span style="color: orange;"&gt;dateFormat&lt;/span&gt;" option. Date format normally depends on user locale and should be passed from outside.&lt;br /&gt;&lt;br /&gt;P.S. Just now I found a &lt;a href="http://kmymoney2.sourceforge.net/online-manual/reference.widgets.html"&gt;desktop example&lt;/a&gt; of such combined calendar too. So, you see, it's an useful and established widget :-).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-416618731653400964?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/416618731653400964/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/08/combine-jquery-datepicker-and-spinner.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/416618731653400964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/416618731653400964'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/08/combine-jquery-datepicker-and-spinner.html' title='Combine jQuery Datepicker and Spinner for fast day incrementation / decrementation'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-9GJEjN04Mtc/Tla-XVJJdVI/AAAAAAAAAFY/hD3h8MLPW8A/s72-c/dateSpinner.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-5307485192775607378</id><published>2011-08-21T15:52:00.000-07:00</published><updated>2011-08-22T01:01:30.524-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='GWT'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>GWT composite widgets vs. JSF composite components</title><content type='html'>I have started to learn &lt;span style="color: orange;"&gt;GWT&lt;/span&gt; (&lt;a href="http://code.google.com/intl/en/webtoolkit/gettingstarted.html"&gt;Google Web Toolkit&lt;/a&gt;). I don't want to compare all features of both frameworks. I would like to pick just one feature. In GWT you can write autonomous and reusable composite widgets and apply them many times on one or several pages. GWT following say that's not really possible in JSF 2 because one composite component is normally linked with a managed bean. If you use the same composite component twice and change value(s) in one composite component, changed value(s) will be propogated through the bean to another component too. Is it really true?&lt;br /&gt;&lt;br /&gt;Take an example. Assume, we have to write a composite widget / component consist of a label, an input field and a button which are aligned horizontally. The GWT solution could be looked like this one&lt;br /&gt;&lt;pre class="brush:java"&gt;public class CompositeExample implements EntryPoint&lt;br /&gt;{&lt;br /&gt;	private static class LabeledInput extends Composite {&lt;br /&gt;		private Label label = new Label();&lt;br /&gt;		private TextBox textBox = new TextBox();&lt;br /&gt;		private Button button = new Button("Jump!", new ClickHandler() {&lt;br /&gt;			public void onClick(ClickEvent event) {&lt;br /&gt;				// do something&lt;br /&gt;			}&lt;br /&gt;		});&lt;br /&gt;&lt;br /&gt;		public LabeledInput() {&lt;br /&gt;			HorizontalPanel panel = new HorizontalPanel();&lt;br /&gt;			panel.add(label);&lt;br /&gt;			panel.add(textBox);&lt;br /&gt;			panel.add(button);&lt;br /&gt;&lt;br /&gt;			initWidget(panel);&lt;br /&gt;		}&lt;br /&gt;	}&lt;br /&gt;&lt;br /&gt;	public void onModuleLoad() {&lt;br /&gt;		LabeledInput labeledInput = new LabeledInput();&lt;br /&gt;		RootPanel.get().add(labeledInput);&lt;br /&gt;	}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;I defined a class named &lt;span style="color: orange;"&gt;LabeledInput&lt;/span&gt; which extends the class &lt;span style="color: orange;"&gt;com.google.gwt.user.client.ui.Composite&lt;/span&gt;. The new composite widget &lt;span style="color: orange;"&gt;LabeledInput&lt;/span&gt; is well reusable many times on any pages. No problems here. A corresponding JSF solution could be implemented in a file &lt;span style="color: orange;"&gt;labeledInput.xhtml&lt;/span&gt; as follows&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt;	  xmlns:h="http://java.sun.com/jsf/html"&lt;br /&gt;	  xmlns:cc="http://java.sun.com/jsf/composite"&amp;gt;&lt;br /&gt;&amp;lt;cc:interface&amp;gt;&lt;br /&gt;	&amp;lt;cc:attribute name="model" required="true"&amp;gt;&lt;br /&gt;		&amp;lt;cc:attribute name="labelValue" required="true"/&amp;gt;&lt;br /&gt;		&amp;lt;cc:attribute name="inputValue" required="true"/&amp;gt;&lt;br /&gt;		&amp;lt;cc:attribute name="jump" required="true" method-signature="void f(javax.faces.event.ActionEvent)"/&amp;gt;&lt;br /&gt;	&amp;lt;/cc:attribute&amp;gt;&lt;br /&gt;	&amp;lt;cc:actionSource name="jump"/&amp;gt;&lt;br /&gt;&amp;lt;/cc:interface&amp;gt;&lt;br /&gt;&amp;lt;cc:implementation&amp;gt;&lt;br /&gt;	&amp;lt;h:panelGrid columns="3"&amp;gt;&lt;br /&gt;		&amp;lt;h:outputLabel for="#{cc.clientId}:input" value="#{cc.attrs.model.labelValue}"/&amp;gt;&lt;br /&gt;		&amp;lt;h:inputText id="input" value="#{cc.attrs.model.inputValue}"/&amp;gt;&lt;br /&gt;		&amp;lt;h:commandButton value="Jump!" actionListener="#{cc.attrs.model.jump}"/&amp;gt;&lt;br /&gt;	&amp;lt;/h:panelGrid&amp;gt;&lt;br /&gt;&amp;lt;/cc:implementation&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: orange;"&gt;cc:attribute&lt;/span&gt; "&lt;span style="color: orange;"&gt;model&lt;/span&gt;" should point to a managed bean having attributes "&lt;span style="color: orange;"&gt;labelValue&lt;/span&gt;", "&lt;span style="color: orange;"&gt;inputValue&lt;/span&gt;" and method (actionListener) "&lt;span style="color: orange;"&gt;jump&lt;/span&gt;". Using of this custom component is simple&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;h:form&amp;gt;&lt;br /&gt;	...&lt;br /&gt;	&amp;lt;custom:labeledInput id="cli1" model="#{someBean}"&amp;gt;&lt;br /&gt;	...&lt;br /&gt;&amp;lt;/h:form&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;h:form&amp;gt;&lt;br /&gt;	...&lt;br /&gt;	&amp;lt;custom:labeledInput id="cli2" model="#{someBean}"&amp;gt;&lt;br /&gt;	...&lt;br /&gt;&amp;lt;/h:form&amp;gt;&lt;br /&gt;&lt;/pre&gt;There is a problem with this JSF solution. If you change the input value (field &lt;span style="color: orange;"&gt;h:inputText&lt;/span&gt;) in the first component and submit the surrounding form, the new value is going to set into the bean "&lt;span style="color: orange;"&gt;someBean&lt;/span&gt;". This bean is also used by the second component. That means, the second component gets the changed value what is not a desired behavior of course. But JSF is powerful enough to solve this problem. There is a possibility to mix JSF components written in Java with declarative code written in XHTML. We can write a class &lt;span style="color: orange;"&gt;LabeledInput&lt;/span&gt; extending &lt;span style="color: orange;"&gt;UINamingContainer&lt;/span&gt; (according to specification) for our composite component. This class encapsulates then all attributes and has the mentioned above actionListener method.&lt;br /&gt;&lt;pre class="brush:java"&gt;@FacesComponent("mypackage.LabeledInput")&lt;br /&gt;public class LabeledInput extends UINamingContainer&lt;br /&gt;{&lt;br /&gt;	enum PropertyKeys {labelValue, inputValue, jump;}&lt;br /&gt;&lt;br /&gt;    public Object getLabelValue() {&lt;br /&gt;		return getStateHelper().eval(PropertyKeys.labelValue);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setLabelValue(Object labelValue) {&lt;br /&gt;		getStateHelper().put(PropertyKeys.labelValue, labelValue);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Object getInputValue() {&lt;br /&gt;		return getStateHelper().eval(PropertyKeys.inputValue);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setInputValue(Object inputValue) {&lt;br /&gt;		getStateHelper().put(PropertyKeys.inputValue, inputValue);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;	public void jump(ActionEvent e) {&lt;br /&gt;		// do something&lt;br /&gt;	}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Component class can be linked now with the XHTML part via "&lt;span style="color: orange;"&gt;componentType&lt;/span&gt;" attribute in &lt;span style="color: orange;"&gt;cc:interface&lt;/span&gt;. Important part to be changed looks then as follows&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;cc:interface componentType="mypackage.LabeledInput"&amp;gt;&lt;br /&gt;	&amp;lt;cc:attribute name="labelValue"/&amp;gt;&lt;br /&gt;	&amp;lt;cc:attribute name="inputValue"/&amp;gt;&lt;br /&gt;	&amp;lt;cc:actionSource name="jump"/&amp;gt;&lt;br /&gt;&amp;lt;/cc:interface&amp;gt;&lt;br /&gt;&amp;lt;cc:implementation&amp;gt;&lt;br /&gt;	&amp;lt;h:panelGrid columns="3"&amp;gt;&lt;br /&gt;		&amp;lt;h:outputLabel for="#{cc.clientId}:input" value="#{cc.labelValue}"/&amp;gt;&lt;br /&gt;		&amp;lt;h:inputText id="input" value="#{cc.inputValue}"/&amp;gt;&lt;br /&gt;		&amp;lt;h:commandButton value="Jump!" actionListener="#{cc.jump}"/&amp;gt;&lt;br /&gt;	&amp;lt;/h:panelGrid&amp;gt;&lt;br /&gt;&amp;lt;/cc:implementation&amp;gt;&lt;br /&gt;&lt;/pre&gt;Managed bean is not needed to be passed by this way. Now we can speak about an autonomous and reusable composite component and write &lt;span style="color: orange;"&gt;&amp;lt;custom:labeledInput&amp;gt;&lt;/span&gt; on a page as much as we want without any collisions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-5307485192775607378?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/5307485192775607378/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/08/gwt-composite-widgets-vs-jsf-composite.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/5307485192775607378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/5307485192775607378'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/08/gwt-composite-widgets-vs-jsf-composite.html' title='GWT composite widgets vs. JSF composite components'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-277896922302499901</id><published>2011-07-21T08:15:00.000-07:00</published><updated>2011-07-21T08:15:27.938-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Raphaël'/><title type='text'>Raphaël Library evaluated</title><content type='html'>About three months ago I was evaluating &lt;a href="http://raphaeljs.com/"&gt;JavaScript Library Raphaël&lt;/a&gt;. This is a library for simplifying the work with vector graphics on the web. It uses SVG and VML (Internet Explorer), is highly compatible with every browser environment and doesn't depend on Flash or Canvas. I'm developing a collaborative online whiteboard just now by means of Raphaël and several frameworks for bidirectional communication in the web. Presentation is coming soon. I will also post examples how to use Raphaël library to draw shapes and more in the web. In this post I just wanted to tell that my first example (at the beginning of my evaluation) has been included to the known &lt;a href="http://www.irunmywebsite.com/raphael/raphaelsource.php"&gt;Raphaël Source Examples&lt;/a&gt;. You find it there under "&lt;span style="color: orange;"&gt;Other related sites&lt;/span&gt;" as "&lt;span style="color: orange;"&gt;Oleg's online collaborative whiteboard is evolving&lt;/span&gt;". &lt;a href="http://fractalsoft.de/drawing/drawing.html"&gt;The direct link to the test application is here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Have much fun with Raphaël ;-)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-MxdaSbs8MtA/TihCSty79wI/AAAAAAAAAFU/TAF6oZ-JgRQ/s1600/TestRaphaelDrawing.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="499" src="http://2.bp.blogspot.com/-MxdaSbs8MtA/TihCSty79wI/AAAAAAAAAFU/TAF6oZ-JgRQ/s640/TestRaphaelDrawing.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-277896922302499901?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/277896922302499901/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/07/raphael-library-evaluated.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/277896922302499901'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/277896922302499901'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/07/raphael-library-evaluated.html' title='Raphaël Library evaluated'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-MxdaSbs8MtA/TihCSty79wI/AAAAAAAAAFU/TAF6oZ-JgRQ/s72-c/TestRaphaelDrawing.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-5304101744228554523</id><published>2011-07-21T07:37:00.000-07:00</published><updated>2011-07-21T07:41:14.050-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='PrimeFaces'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='Ajax'/><title type='text'>Unified JSF Connection (Ajax) Status Indicator</title><content type='html'>Real JSF web applications consist of various ajaxifed components. The good practise is to tell users that they should be waiting for something to finish. A global Ajax Status Indicator seems to be very handy in ajaxifed applications. Such components exist e.g. in RichFaces, ICEFaces and PrimeFaces. If you only use one of these component libraries, you can skip this post :-) But what is about if you use a mix composed of standard &lt;span style="color: orange;"&gt;f:ajax&lt;/span&gt; with any standard and not standard components + ajaxified components from any libraries? I have counted &lt;span style="color: orange;"&gt;f:ajax&lt;/span&gt; and PrimeFaces' &lt;span style="color: orange;"&gt;p:ajax&lt;/span&gt; appearances in my applications. Approximately 50% to 50%. Probably you used &lt;span style="color: orange;"&gt;f:ajax&lt;/span&gt; too because &lt;span style="color: orange;"&gt;p:ajax&lt;/span&gt; had issues in early PrimeFaces versions. The question is now how to adjust &lt;span style="color: orange;"&gt;p:ajaxStatus&lt;/span&gt; in order to consider standard Ajax requests in addition to PrimeFaces Ajax requests based on jQuery Ajax? We can add global callbacks for event handling from standard JSF&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;jsf.ajax.addOnEvent(callback)&lt;br /&gt;jsf.ajax.addOnError(callback)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;Let me extend PrimeFaces &lt;span style="color: orange;"&gt;AjaxStatus&lt;/span&gt;, register new global callbacks and show an example in action. At first we have to add the standard JS library for Ajax and our extended script &lt;span style="color: orange;"&gt;ajaxstatus.js&lt;/span&gt;.&lt;br /&gt;&lt;pre class="brush:java"&gt;import javax.faces.application.ResourceDependencies;&lt;br /&gt;import javax.faces.application.ResourceDependency;&lt;br /&gt;&lt;br /&gt;@ResourceDependencies({&lt;br /&gt;    @ResourceDependency(library="primefaces", name="jquery/jquery.js"),&lt;br /&gt;    @ResourceDependency(library="primefaces", name="core/core.js"),&lt;br /&gt;    @ResourceDependency(library="primefaces", name="ajaxstatus/ajaxstatus.js"),&lt;br /&gt;    @ResourceDependency(library="javax.faces", name="jsf.js"),&lt;br /&gt;    @ResourceDependency(library="js", name="ajaxstatus.js")&lt;br /&gt;})&lt;br /&gt;public class AjaxStatus extends org.primefaces.component.ajaxstatus.AjaxStatus&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Renderer class is simple&lt;br /&gt;&lt;pre class="brush:java"&gt;import javax.faces.context.FacesContext;&lt;br /&gt;import javax.faces.context.ResponseWriter;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;&lt;br /&gt;public class AjaxStatusRenderer extends org.primefaces.component.ajaxstatus.AjaxStatusRenderer&lt;br /&gt;{&lt;br /&gt;    protected void encodeScript(FacesContext context, org.primefaces.component.ajaxstatus.AjaxStatus st)&lt;br /&gt;        throws IOException {&lt;br /&gt;        AjaxStatus status = (AjaxStatus)st;&lt;br /&gt;        ResponseWriter writer = context.getResponseWriter();&lt;br /&gt;        String clientId = status.getClientId(context);&lt;br /&gt;        String widgetVar = status.resolveWidgetVar();&lt;br /&gt;&lt;br /&gt;        writer.startElement("script", null);&lt;br /&gt;        writer.writeAttribute("type", "text/javascript", null);&lt;br /&gt;&lt;br /&gt;        writer.write(widgetVar + " = new PrimeFaces.widget.ExtendedAjaxStatus('" + clientId + "');");&lt;br /&gt;&lt;br /&gt;        encodeCallback(context, status, widgetVar, "ajaxSend", "onprestart", AjaxStatus.PRESTART_FACET);&lt;br /&gt;        encodeCallback(context, status, widgetVar, "ajaxStart", "onstart", AjaxStatus.START_FACET);&lt;br /&gt;        encodeCallback(context, status, widgetVar, "ajaxError", "onerror", AjaxStatus.ERROR_FACET);&lt;br /&gt;        encodeCallback(context, status, widgetVar, "ajaxSuccess", "onsuccess", AjaxStatus.SUCCESS_FACET);&lt;br /&gt;        encodeCallback(context, status, widgetVar, "ajaxComplete", "oncomplete", AjaxStatus.COMPLETE_FACET);&lt;br /&gt;&lt;br /&gt;        writer.endElement("script");&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Note: Prestart event "&lt;span style="color: orange;"&gt;ajaxSend&lt;/span&gt;" is not supported in the standard Ajax, but it's rarely used anyway. "&lt;span style="color: orange;"&gt;ajaxStart&lt;/span&gt;" is normally enough. JavaScript &lt;span style="color: orange;"&gt;ajaxstatus.js&lt;/span&gt; is a little bit complicate. I register there global handlers for Ajax events by &lt;span style="color: orange;"&gt;jsf.ajax.addOnError&lt;/span&gt; / &lt;span style="color: orange;"&gt;jsf.ajax.addOnEvent&lt;/span&gt;.&lt;br /&gt;&lt;pre class="brush:js"&gt;PrimeFaces.widget.ExtendedAjaxStatus = function(id) {&lt;br /&gt;    this.id = id;&lt;br /&gt;    this.jqId = PrimeFaces.escapeClientId(this.id);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PrimeFaces.widget.ExtendedAjaxStatus.prototype.bindFacet = function(eventName, facetToShow) {&lt;br /&gt;    var _self = this;&lt;br /&gt;&lt;br /&gt;    // jQuery&lt;br /&gt;    jQuery(document).bind(eventName, function() {&lt;br /&gt;        _self.showFacet(facetToShow);&lt;br /&gt;    });&lt;br /&gt;&lt;br /&gt;    // Standard&lt;br /&gt;    if (eventName == "ajaxError") {&lt;br /&gt;        jsf.ajax.addOnError(this.processAjaxOnErrorFacet(facetToShow));&lt;br /&gt;    } else {&lt;br /&gt;        jsf.ajax.addOnEvent(this.processAjaxOnEventFacet(eventName, facetToShow));&lt;br /&gt;    }    &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PrimeFaces.widget.ExtendedAjaxStatus.prototype.bindCallback = function(eventName, fn) {&lt;br /&gt;    // jQuery&lt;br /&gt;    jQuery(document).bind(eventName, fn);&lt;br /&gt;&lt;br /&gt;    // Standard&lt;br /&gt;    if (eventName == "ajaxError") {&lt;br /&gt;        jsf.ajax.addOnError(this.processAjaxOnErrorCallback(fn));&lt;br /&gt;    } else {&lt;br /&gt;        jsf.ajax.addOnEvent(this.processAjaxOnEventCallback(eventName, fn));&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PrimeFaces.widget.ExtendedAjaxStatus.prototype.processAjaxOnEventFacet = function(eventName, facetToShow) {&lt;br /&gt;    var _self = this;&lt;br /&gt;&lt;br /&gt;    function processEvent(data) {&lt;br /&gt;        if (eventName == "ajaxStart" &amp;amp;&amp;amp; data.status == "begin") {&lt;br /&gt;            _self.showFacet(facetToShow);&lt;br /&gt;        } else if (eventName == "ajaxComplete" &amp;amp;&amp;amp; data.status == "complete") {&lt;br /&gt;            _self.showFacet(facetToShow);&lt;br /&gt;        } else if (eventName == "ajaxSuccess" &amp;amp;&amp;amp; data.status == "success") {&lt;br /&gt;            _self.showFacet(facetToShow);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return processEvent;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PrimeFaces.widget.ExtendedAjaxStatus.prototype.processAjaxOnErrorFacet = function(facetToShow) {&lt;br /&gt;    var _self = this;&lt;br /&gt;&lt;br /&gt;    function processEvent() {&lt;br /&gt;        _self.showFacet(facetToShow);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return processEvent;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PrimeFaces.widget.ExtendedAjaxStatus.prototype.processAjaxOnEventCallback = function(eventName, fn) {&lt;br /&gt;    function processEvent(data) {&lt;br /&gt;        if (eventName == "ajaxStart" &amp;amp;&amp;amp; data.status == "begin") {&lt;br /&gt;            fn();&lt;br /&gt;        } else if (eventName == "ajaxComplete" &amp;amp;&amp;amp; data.status == "complete") {&lt;br /&gt;            fn();&lt;br /&gt;        } else if (eventName == "ajaxSuccess" &amp;amp;&amp;amp; data.status == "success") {&lt;br /&gt;            fn();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return processEvent;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PrimeFaces.widget.ExtendedAjaxStatus.prototype.processAjaxOnErrorCallback = function(fn) {&lt;br /&gt;    function processEvent() {&lt;br /&gt;        fn();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return processEvent;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PrimeFaces.widget.ExtendedAjaxStatus.prototype.showFacet = function(facetToShow) {&lt;br /&gt;    jQuery(this.jqId).children().hide();&lt;br /&gt;    jQuery(this.jqId + '_' + facetToShow).show();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Using on the page along with JS handling could be&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;p:ajaxStatus onstart="ajaxOnStartIndicator()" onerror="ajaxOnErrorIndicator()" onsuccess="ajaxOnSuccessIndicator()"/&amp;gt;&lt;br /&gt;&amp;lt;h:graphicImage id="ajaxIndicatorActive" library="img" name="connect_active.gif"&lt;br /&gt;    style="display: none;" styleClass="ajaxIndicator"/&amp;gt;&lt;br /&gt;&amp;lt;h:graphicImage id="ajaxIndicatorCaution" library="img" name="connect_caution.gif"&lt;br /&gt;    style="display: none;" styleClass="ajaxIndicator" title="Connection problem" alt="Connection problem"/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre class="brush:js"&gt;function ajaxOnStartIndicator() {&lt;br /&gt;    document.body.style.cursor = 'wait';&lt;br /&gt;    jQuery("#ajaxIndicatorCaution").css("display", "none");&lt;br /&gt;    jQuery("#ajaxIndicatorActive").css("display", "block");&lt;br /&gt;&lt;br /&gt;    // get the current counter&lt;br /&gt;    var jqDoc = jQuery(document);&lt;br /&gt;    var requestCount = jqDoc.data("ajaxStatus.requestCount");&lt;br /&gt;    if (typeof requestCount === 'undefined') {&lt;br /&gt;        requestCount = 0;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // increase the counter&lt;br /&gt;    jqDoc.data("ajaxStatus.requestCount", requestCount+1);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function ajaxOnSuccessIndicator() {&lt;br /&gt;    // get the current counter&lt;br /&gt;    var jqDoc = jQuery(document);&lt;br /&gt;    var requestCount = jqDoc.data("ajaxStatus.requestCount");&lt;br /&gt;&lt;br /&gt;    // check the counter&lt;br /&gt;    if (typeof requestCount !== 'undefined') {&lt;br /&gt;        if (requestCount == 1) {&lt;br /&gt;            // hide indicators&lt;br /&gt;            document.body.style.cursor = 'auto';&lt;br /&gt;            jQuery("#ajaxIndicatorActive").css("display", "none");&lt;br /&gt;            jQuery("#ajaxIndicatorCaution").css("display", "none");&lt;br /&gt;            jqDoc.data("ajaxStatus.requestCount", 0);&lt;br /&gt;        } else if (requestCount &amp;gt; 1) {&lt;br /&gt;            // only decrease the counter&lt;br /&gt;            jqDoc.data("ajaxStatus.requestCount", requestCount-1);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function ajaxOnErrorIndicator() {&lt;br /&gt;    document.body.style.cursor = 'auto';&lt;br /&gt;    jQuery("#ajaxIndicatorActive").css("display", "none");&lt;br /&gt;    jQuery("#ajaxIndicatorCaution").css("display", "block");&lt;br /&gt;    // reset counter&lt;br /&gt;    jQuery(document).data("ajaxStatus.requestCount", 0);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The implementation is smart enough and avoid collisions with parallel running Ajax requests (s. counters). Furthermore, the cursor is set to '&lt;span style="color: orange;"&gt;wait&lt;/span&gt;' if an Ajax request is running. It's how desktop applications behaves.&lt;br /&gt;&lt;br /&gt;I took connection icons from &lt;a href="http://component-showcase.icefaces.org/component-showcase/showcase.iface"&gt;ICEFaces showcase&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-bxqnYWPnmVg/Tig3YiDgG4I/AAAAAAAAAFQ/T-WrRVa-b50/s1600/AjaxIndicators.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-bxqnYWPnmVg/Tig3YiDgG4I/AAAAAAAAAFQ/T-WrRVa-b50/s1600/AjaxIndicators.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-5304101744228554523?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/5304101744228554523/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/07/unified-jsf-connection-ajax-status.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/5304101744228554523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/5304101744228554523'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/07/unified-jsf-connection-ajax-status.html' title='Unified JSF Connection (Ajax) Status Indicator'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-bxqnYWPnmVg/Tig3YiDgG4I/AAAAAAAAAFQ/T-WrRVa-b50/s72-c/AjaxIndicators.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-8212983439729103753</id><published>2011-07-13T07:30:00.000-07:00</published><updated>2011-07-13T08:37:02.045-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='PrimeFaces'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>Filter keyboard input of JSF input components</title><content type='html'>&lt;a href="http://code.google.com/p/jquery-keyfilter/"&gt;jQuery keyfilter plugin&lt;/a&gt; is a good choice if you want to filter input by specified regular expression. It allows you to input only specified characters via regular expression. Assume, your input field has an ID "&lt;span style="color: orange;"&gt;myinput&lt;/span&gt;" and you want to restrict any user input to hexadecimal characters. This task can be done as follows&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;$('#myinput').keyfilter(/[0-9a-f]/i);&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;You can also pass a test function instead of regular expression. It expects two arguments: event target (DOM element) and incoming character. If the return value is true, the input character is valid and allowed, otherwise - not.&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;$('#myinput').keyfilter(function(c) {&lt;br /&gt;    return c != 'a';&lt;br /&gt;});&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;Easy? There are a lot of predefined masks too - for numeric, alphanumeric, etc. signs. &lt;i&gt;Do we have something like in JSF?&lt;/i&gt; No. Well, there is a component &lt;span style="color: orange;"&gt;MaskedInput&lt;/span&gt; in PrimeFaces, but it's restricted to a fix length. Length of the input value can not be variable and there is a very small set of signs to configure input masks. Conclusion - poor component :-). Keyfilter covers &lt;span style="color: orange;"&gt;MaskedInput &lt;/span&gt;and offers more flexibility. &lt;i&gt;Can we implement the keyfilter functionality in JSF?&lt;/i&gt; Yes, ideally as client behavior. The aim of this post is not this implementation. The aim of this topic is to show how to attach this functionality to an existing JSF component (hard-coded). I would like to take PrimeFaces &lt;span style="color: orange;"&gt;AutoComplete&lt;/span&gt;. I would also like to show a tooltip if user input some disallowed characters. Let's start. We extend the component class by adding new resources - CSS and JS files for jQuery &lt;span style="color: orange;"&gt;tooltip&lt;/span&gt; (qTip2), &lt;span style="color: orange;"&gt;keyfilter&lt;/span&gt; plugins and an own extension for the &lt;span style="color: orange;"&gt;AutoComplete &lt;/span&gt;widget.&lt;br /&gt;&lt;pre class="brush:java"&gt;@ResourceDependencies({&lt;br /&gt;    @ResourceDependency(library="primefaces", name="forms/forms.css"),&lt;br /&gt;    @ResourceDependency(library="primefaces", name="jquery/ui/jquery-ui.css"),&lt;br /&gt;    @ResourceDependency(library="primefaces", name="jquery/jquery.js"),&lt;br /&gt;    @ResourceDependency(library="primefaces", name="jquery/ui/jquery-ui.js"),&lt;br /&gt;    @ResourceDependency(library="primefaces", name="core/core.js"),&lt;br /&gt;    @ResourceDependency(library="primefaces", name="autocomplete/autocomplete.js"),&lt;br /&gt;    @ResourceDependency(library = "css", name = "jquery.qtip.css"),&lt;br /&gt;    @ResourceDependency(library = "js", name = "tooltip/jquery.qtip.js"),&lt;br /&gt;    @ResourceDependency(library = "js", name = "autocomplete/jquery.keyfilter.js"),&lt;br /&gt;    @ResourceDependency(library = "js", name = "autocomplete/autocomplete.js")&lt;br /&gt;})&lt;br /&gt;public class AutoComplete extends org.primefaces.component.autocomplete.AutoComplete {&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;In the &lt;span style="color: orange;"&gt;AutoCompleteRenderer.java&lt;/span&gt; we add these lines to &lt;span style="color: orange;"&gt;encodeScript()&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;// get tooltip text for invalid characters&lt;br /&gt;String tooltipText = MessageUtils.getMessageText(facesContext,&lt;br /&gt;    facesContext.getApplication().getMessageBundle(), "autocomplete.invalidChars");&lt;br /&gt;if (tooltipText != null) {&lt;br /&gt;    tooltipText = tooltipText.replaceAll("'", "\\\\'");&lt;br /&gt;} else {&lt;br /&gt;    // fallback&lt;br /&gt;    tooltipText = "Input character is not allowed";&lt;br /&gt;}&lt;br /&gt;writer.write(",tooltipText:'" + tooltipText + "'");&lt;br /&gt;&lt;/pre&gt;I used here an own utility class &lt;span style="color: orange;"&gt;MessageUtils &lt;/span&gt;to get a message from message bundle. The most complicated step is the writing of an extended widget.&lt;br /&gt;&lt;pre class="brush:js"&gt;PrimeFaces.widget.ExtendedAutoComplete = function(id, cfg) {&lt;br /&gt;    this.superWidget = PrimeFaces.widget.AutoComplete;&lt;br /&gt;    this.superWidget(id, cfg);&lt;br /&gt;    var _self = this;&lt;br /&gt;&lt;br /&gt;    // initialize flag whether the current input character is valid&lt;br /&gt;    this.jq.data("allowedChar", true);&lt;br /&gt;&lt;br /&gt;    // define tooltip&lt;br /&gt;    this.jq.qtip({&lt;br /&gt;        content: {&lt;br /&gt;            text: cfg.tooltipText&lt;br /&gt;        },&lt;br /&gt;        style: {&lt;br /&gt;            widget: true,&lt;br /&gt;            classes: 'ui-tooltip-rounded ui-tooltip-shadow'&lt;br /&gt;        },&lt;br /&gt;        position: {&lt;br /&gt;            my: 'bottom center',&lt;br /&gt;            at: 'top center'&lt;br /&gt;        },&lt;br /&gt;        events: {&lt;br /&gt;            show: function(event, api) {&lt;br /&gt;                try {&lt;br /&gt;                    if (_self.jq.data("allowedChar")) {&lt;br /&gt;                        event.preventDefault();&lt;br /&gt;                    }&lt;br /&gt;                } catch(e) {&lt;br /&gt;                    // IE can throw an error&lt;br /&gt;                }&lt;br /&gt;            },&lt;br /&gt;            hide: function(event, api) {&lt;br /&gt;                _self.jq.data("allowedChar", true);&lt;br /&gt;            }&lt;br /&gt;        },&lt;br /&gt;        show: {&lt;br /&gt;            event: false&lt;br /&gt;        },&lt;br /&gt;        hide: {&lt;br /&gt;            event: 'blur'&lt;br /&gt;        }&lt;br /&gt;    });&lt;br /&gt;&lt;br /&gt;    // filter input&lt;br /&gt;    this.filterKeys(cfg);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;jQuery.extend(PrimeFaces.widget.ExtendedAutoComplete.prototype, PrimeFaces.widget.AutoComplete.prototype);&lt;br /&gt;&lt;br /&gt;PrimeFaces.widget.ExtendedAutoComplete.prototype.filterKeys = function(cfg) {&lt;br /&gt;    var _self = this;&lt;br /&gt;&lt;br /&gt;    _self.jq.keyfilter(function(c) {&lt;br /&gt;        var isAllow = _self.allowChar(c);&lt;br /&gt;        _self.jq.data("allowedChar", isAllow);&lt;br /&gt;&lt;br /&gt;        if (cfg.pojo) {&lt;br /&gt;            _self.jq.unbind('keyup');&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        if (isAllow) {&lt;br /&gt;            // hide tooltip&lt;br /&gt;            _self.jq.qtip('hide');&lt;br /&gt;&lt;br /&gt;            if (cfg.pojo) {&lt;br /&gt;                _self.jq.keyup(function(e) {&lt;br /&gt;                    if (e.keyCode != 13) {&lt;br /&gt;                        jQuery(_self.jqh).val(jQuery(this).val());&lt;br /&gt;                    }&lt;br /&gt;                });&lt;br /&gt;            }&lt;br /&gt;        } else {&lt;br /&gt;            // show tooltip&lt;br /&gt;            _self.jq.qtip('show');&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return isAllow;&lt;br /&gt;    });&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PrimeFaces.widget.ExtendedAutoComplete.prototype.allowChar = function(c) {&lt;br /&gt;    return c != '%' &amp;amp;&amp;amp; c != '?' &amp;amp;&amp;amp; c != '&amp;amp;';&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;I wrote here a test function instead of regular expression to prevent &lt;span style="color: orange;"&gt;% ? &amp;amp;&lt;/span&gt; signs to be input. The result looks pretty fine&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-_YdUZAKLtCM/Th2rM5peU8I/AAAAAAAAAFI/YdVxG_XEceI/s1600/TooltipAutoComplete.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-_YdUZAKLtCM/Th2rM5peU8I/AAAAAAAAAFI/YdVxG_XEceI/s1600/TooltipAutoComplete.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-8212983439729103753?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/8212983439729103753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/07/filter-keyboard-input-of-jsf-input.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/8212983439729103753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/8212983439729103753'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/07/filter-keyboard-input-of-jsf-input.html' title='Filter keyboard input of JSF input components'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-_YdUZAKLtCM/Th2rM5peU8I/AAAAAAAAAFI/YdVxG_XEceI/s72-c/TooltipAutoComplete.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-7584133142674008155</id><published>2011-07-06T02:26:00.000-07:00</published><updated>2011-07-06T08:27:15.783-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><title type='text'>Cross-browser fonts (aka @font-face)</title><content type='html'>Recently I have experimented with web fonts to figure out the best one and take it as standard for my company. There are not much predefined web fonts at all. "&lt;span style="color: orange;"&gt;Verdana&lt;/span&gt;" was too wide for me, "&lt;span style="color: orange;"&gt;Arial&lt;/span&gt;" was too narrow, "&lt;span style="color: orange;"&gt;Tahoma&lt;/span&gt;" and "&lt;span style="color: orange;"&gt;Trebuchet MS&lt;/span&gt;" were different displayed dependent on browser, ... I ended up with a cross browser font face implementation. There are many wonderful fonts which can be added to web applications by using of &lt;span style="color: orange;"&gt;@font-face&lt;/span&gt;. &lt;span style="color: orange;"&gt;@font-face&lt;/span&gt; is a css rule which allows you to download a particular font from your server to render a webpage if the user hasn't got that font installed. &lt;span style="color: orange;"&gt;@font-face&lt;/span&gt; is supported by all browsers, even old Internet Explorer. There are dozens of Internet ressources with quality and amazing fonts. For instance, go to the &lt;a href="http://www.fontsquirrel.com/"&gt;Font Squirrel&lt;/a&gt;. That's the best resource for free, high-quality, commercial-use fonts. Choose a font and download a &lt;span style="color: orange;"&gt;@font-face kit&lt;/span&gt; for it (a zip file). You need four types of font files. Each &lt;span style="color: orange;"&gt;@font-face kit&lt;/span&gt; come with:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;EOT fonts for Internet Explorer 4+&lt;/li&gt;&lt;li&gt;TrueType fonts for Firefox 3.5+ , Opera 10+, Safari 3.1+, Chrome 4.0.249.4+&lt;/li&gt;&lt;li&gt;WOFF fonts for Firefox 3.6+, Internet Explorer 9+, Chrome 5+&lt;/li&gt;&lt;li&gt;SVG fonts for iPad and iPhone&lt;/li&gt;&lt;/ol&gt;After downloading unpack the zip file somewhere in your web application. You will find files with extensions &lt;span style="color: orange;"&gt;.eot&lt;/span&gt;, &lt;span style="color: orange;"&gt;.ttf&lt;/span&gt;, &lt;span style="color: orange;"&gt;.woff&lt;/span&gt;, &lt;span style="color: orange;"&gt;.svg&lt;/span&gt; and a &lt;span style="color: orange;"&gt;stylesheet.css&lt;/span&gt;. &lt;span style="color: orange;"&gt;stylesheet.css&lt;/span&gt; has ready-to-use definitions - examples how to add &lt;span style="color: orange;"&gt;@font-face&lt;/span&gt; for the desired font to your web application. Assume, you have choosen a font named as "&lt;span style="color: orange;"&gt;BPreplayRegular&lt;/span&gt;". &lt;span style="color: orange;"&gt;@font-face&lt;/span&gt; will look like then as follows&lt;br /&gt;&lt;pre class="brush:css"&gt;@font-face {&lt;br /&gt;    font-family: 'BPreplayRegular';&lt;br /&gt;    src: url('BPreplay-webfont.eot');&lt;br /&gt;    src: url('BPreplay-webfont.eot?#iefix') format('embedded-opentype'),&lt;br /&gt;         url('BPreplay-webfont.woff') format('woff'),&lt;br /&gt;         url('BPreplay-webfont.ttf') format('truetype'),&lt;br /&gt;         url('BPreplay-webfont.svg#BPreplayRegular') format('svg');&lt;br /&gt;    font-weight: normal;&lt;br /&gt;    font-style: normal;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;To match your directory structure you should set right paths to your four files in "&lt;span style="color: orange;"&gt;url&lt;/span&gt;", of course. After that you are able to apply the font to any HTML element, e.g.&lt;br /&gt;&lt;pre class="brush:css"&gt;body {&lt;br /&gt;    font-family: 'BPreplayRegular', Verdana, sans-serif;&lt;br /&gt;    padding: 0px;&lt;br /&gt;    margin:  0px;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Such web fonts work fine and look identical in IE6-IE9, Firefox, Chrome, Safari, Opera. The good news - there are hundreds of free fonts which leave nothing to be desired.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-7584133142674008155?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/7584133142674008155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/07/cross-browser-fonts-aka-font-face.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7584133142674008155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7584133142674008155'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/07/cross-browser-fonts-aka-font-face.html' title='Cross-browser fonts (aka @font-face)'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-4701167360057630356</id><published>2011-07-01T04:41:00.000-07:00</published><updated>2011-07-01T04:41:35.809-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>Auto updatable JSF components are easy done</title><content type='html'>Do you want to update automatically any JSF components with each ajax response? Are you looking for a dynamic way without needs to touch and change components? Nothing is easier than that. Auto updatable components make sense. They could be messages, tooltips, or everything else what is avalaible on every page and have to be updated. An own &lt;span style="color: orange;"&gt;PartialViewContext &lt;/span&gt;and JSF system events on the component level will help us to archieve this aim. We start with a listener which must be fired on the &lt;span style="color: orange;"&gt;PreRenderComponentEvent&lt;/span&gt;. Components to be auto updated are added there to the view map of the view root. More precisely - client IDs of such components will be added shortly before components get rendered.&lt;br /&gt;&lt;pre class="brush:java"&gt;package com.xyz.webapp.jsf&lt;br /&gt;&lt;br /&gt;import ...&lt;br /&gt;&lt;br /&gt;public class AutoUpdatableComponentListener implements SystemEventListener {&lt;br /&gt;    public static final String AUTO_UPDATED_IDS = "com.xyz.webapp.jsf.AutoUpdatedIds";&lt;br /&gt;&lt;br /&gt;    @SuppressWarnings("unchecked")&lt;br /&gt;    public void processEvent(SystemEvent event) throws AbortProcessingException {&lt;br /&gt;        FacesContext fc = FacesContext.getCurrentInstance();&lt;br /&gt;        if (fc.getPartialViewContext().isAjaxRequest()) {&lt;br /&gt;            // auto updatable component was already added to the view map&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        UIComponent component = (UIComponent) event.getSource();&lt;br /&gt;        Map&amp;lt;String, Object&amp;gt; viewMap = fc.getViewRoot().getViewMap();&lt;br /&gt;        Collection&amp;lt;String&amp;gt; autoUpdatedIds = (Collection&amp;lt;String&amp;gt;) fc.getViewRoot().getViewMap().get(AUTO_UPDATED_IDS);&lt;br /&gt;&lt;br /&gt;        if (autoUpdatedIds == null) {&lt;br /&gt;            autoUpdatedIds = new HashSet&amp;lt;String&amp;gt;();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        autoUpdatedIds.add(component.getClientId());&lt;br /&gt;        viewMap.put(AUTO_UPDATED_IDS, autoUpdatedIds);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public boolean isListenerForSource(Object source) {&lt;br /&gt;        return true;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The view map is accessed in a special implementaion of the &lt;span style="color: orange;"&gt;PartialViewContext &lt;/span&gt;where all client IDs of auto updatable components have to be added to IDs getting from &lt;span style="color: orange;"&gt;getRenderIds()&lt;/span&gt;.&lt;br /&gt;&lt;pre class="brush:java"&gt;package com.xyz.webapp.jsf.context;&lt;br /&gt;&lt;br /&gt;import com.xyz.webapp.jsf.AutoUpdatableComponentListener;&lt;br /&gt;import javax.faces.context.FacesContext;&lt;br /&gt;import javax.faces.context.PartialViewContext;&lt;br /&gt;import javax.faces.context.PartialViewContextWrapper;&lt;br /&gt;import javax.faces.event.PhaseId;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;import java.util.Collection;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;public class MyPartialViewContext extends PartialViewContextWrapper {&lt;br /&gt;    private PartialViewContext wrapped;&lt;br /&gt;&lt;br /&gt;    public MyPartialViewContext(PartialViewContext wrapped) {&lt;br /&gt;        this.wrapped = wrapped;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public PartialViewContext getWrapped() {&lt;br /&gt;        return this.wrapped;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setPartialRequest(boolean isPartialRequest) {&lt;br /&gt;        getWrapped().setPartialRequest(isPartialRequest);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @SuppressWarnings("unchecked")&lt;br /&gt;    public Collection&amp;lt;String&amp;gt; getRenderIds() {&lt;br /&gt;        FacesContext fc = FacesContext.getCurrentInstance();&lt;br /&gt;        if (PhaseId.RENDER_RESPONSE.compareTo(fc.getCurrentPhaseId()) != 0) {&lt;br /&gt;            return getWrapped().getRenderIds();&lt;br /&gt;        } else {&lt;br /&gt;            List&amp;lt;String&amp;gt; ids = new ArrayList&amp;lt;String&amp;gt;(getWrapped().getRenderIds());&lt;br /&gt;            Collection&amp;lt;String&amp;gt; autoUpdatedIds = (Collection&amp;lt;String&amp;gt;) FacesContext.getCurrentInstance().&lt;br /&gt;                getViewRoot().getViewMap().get(AutoUpdatableComponentListener.AUTO_UPDATED_IDS);&lt;br /&gt;&lt;br /&gt;            if (autoUpdatedIds != null) {&lt;br /&gt;                ids.addAll(autoUpdatedIds);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            return ids;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;package com.xyz.webapp.jsf.context;&lt;br /&gt;&lt;br /&gt;import javax.faces.context.FacesContext;&lt;br /&gt;import javax.faces.context.PartialViewContext;&lt;br /&gt;import javax.faces.context.PartialViewContextFactory;&lt;br /&gt;&lt;br /&gt;public class MyPartialViewContextFactory extends PartialViewContextFactory {&lt;br /&gt;    private PartialViewContextFactory parent;&lt;br /&gt;&lt;br /&gt;    public MyPartialViewContextFactory(PartialViewContextFactory parent) {&lt;br /&gt;        this.parent = parent;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public PartialViewContextFactory getWrapped() {&lt;br /&gt;        return this.parent;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public PartialViewContext getPartialViewContext(FacesContext fc) {&lt;br /&gt;        return new MyPartialViewContext(getWrapped().getPartialViewContext(fc));&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;For &lt;span style="color: orange;"&gt;MyPartialViewContext &lt;/span&gt;is important to know that &lt;span style="color: orange;"&gt;getRenderIds()&lt;/span&gt; is called in four JSF lifecycle phases. We are only interesting in the "render response" phase. That is why I made this check&lt;br /&gt;&lt;pre class="brush:java"&gt;if (PhaseId.RENDER_RESPONSE.compareTo(fc.getCurrentPhaseId()) != 0) {&lt;br /&gt;    return getWrapped().getRenderIds();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The last step - register all stuff in the faces-config.xml.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;factory&amp;gt;&lt;br /&gt;    &amp;lt;partial-view-context-factory&amp;gt;&lt;br /&gt;        com.xyz.webapp.jsf.context.MyPartialViewContextFactory&lt;br /&gt;    &amp;lt;/partial-view-context-factory&amp;gt;&lt;br /&gt;&amp;lt;/factory&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;system-event-listener&amp;gt;&lt;br /&gt;    &amp;lt;system-event-listener-class&amp;gt;com.xyz.webapp.jsf.AutoUpdatableComponentListener&amp;lt;/system-event-listener-class&amp;gt;&lt;br /&gt;    &amp;lt;system-event-class&amp;gt;javax.faces.event.PreRenderComponentEvent&amp;lt;/system-event-class&amp;gt;&lt;br /&gt;    &amp;lt;source-class&amp;gt;com.xyz.webapp.jsf.component.MyComponent&amp;lt;/source-class&amp;gt;&lt;br /&gt;&amp;lt;/system-event-listener&amp;gt;&lt;br /&gt;&lt;/pre&gt;I have registered the listener for &lt;span style="color: orange;"&gt;com.xyz.webapp.jsf.component.MyComponent&lt;/span&gt;, but we can made the configuration a little bit more flexible via a config parameter in &lt;span style="color: orange;"&gt;web.xml&lt;/span&gt;.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;context-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;AUTO_UPDATABLE_COMPONENTS&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;&lt;br /&gt;        com.xyz.webapp.jsf.component.MyComponent,&lt;br /&gt;        javax.faces.component.html.HtmlMessage,&lt;br /&gt;        org.primefaces.component.tooltip.Tooltip&lt;br /&gt;    &amp;lt;/param-value&amp;gt;&lt;br /&gt;&amp;lt;/context-param&amp;gt;&lt;br /&gt;&lt;/pre&gt;We have no needs then to specify &lt;span style="color: orange;"&gt;source-class&lt;/span&gt; and the &lt;span style="color: orange;"&gt;isListenerForSource()&lt;/span&gt; method looks like&lt;br /&gt;&lt;pre class="brush:java"&gt;// This is just an example. Evaluation of init parameters should be done outside of the isListenerForSource() of course.&lt;br /&gt;public boolean isListenerForSource(Object source) {&lt;br /&gt;    String components = &lt;br /&gt;        FacesContext.getCurrentInstance().getExternalContext().getInitParameter("AUTO_UPDATABLE_COMPONENTS");&lt;br /&gt;    if (components == null) {&lt;br /&gt;        return false;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    String[] arr = components.split("[,\\s]+");&lt;br /&gt;    for (String component : arr) {&lt;br /&gt;        if (component.equals(source.getClass().getName())) {&lt;br /&gt;            return true;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return false;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;We can go on and configure components client IDs instead of their fully qualified names (better in my opinion). Check against IDs happens in the &lt;span style="color: orange;"&gt;isListenerForSource()&lt;/span&gt; too. More flexible and precise configurations are possible - e.g. client IDs + pages (= view root IDs) where auto updatable components are placed exactly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-4701167360057630356?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/4701167360057630356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/07/auto-updatable-jsf-components-are-easy.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/4701167360057630356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/4701167360057630356'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/07/auto-updatable-jsf-components-are-easy.html' title='Auto updatable JSF components are easy done'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-1081142321944216222</id><published>2011-06-30T14:41:00.000-07:00</published><updated>2011-10-01T12:49:32.331-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='PrimeFaces'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>Global tooltips with PrimeFaces and qTip2</title><content type='html'>&lt;a href="http://www.primefaces.org/"&gt;PrimeFaces&lt;/a&gt; uses &lt;a href="http://craigsworks.com/projects/qtip/"&gt;jQuery qTip plugin in the version 1&lt;/a&gt; for global tooltips which are applied to all HTML elements having &lt;span style="color: orange;"&gt;title&lt;/span&gt; attribute. There is an issue with ajax updates - global tooltips with qTip1 are gone after an ajax update. An ajax update of any element having the &lt;span style="color: orange;"&gt;title&lt;/span&gt; attribute causes disappearance of nice tooltip. Native tooltips are still here but they are very plain, not beautiful and not themes aware. The official statement from the PrimeFaces team - "&lt;i&gt;known issue, won't be fixed for global ones at the moment&lt;/i&gt;". In this post you will see how to resolve this issue in the simple way. The first step is to upgrade the qTip plugin to &lt;a href="http://craigsworks.com/projects/qtip2/download"&gt;qTip2&lt;/a&gt; and write a component class. The component class extends PrimeFaces' one and overwrites all methods what tooltip's default values have been changed for.&lt;br /&gt;&lt;pre class="brush:java"&gt;@ResourceDependencies({&lt;br /&gt;    @ResourceDependency(library="primefaces", name="jquery/jquery.js"),&lt;br /&gt;    @ResourceDependency(library="primefaces", name="core/core.js"),&lt;br /&gt;    @ResourceDependency(library = "css", name = "jquery.qtip.css"),&lt;br /&gt;    @ResourceDependency(library = "js", name = "tooltip/jquery.qtip.js"),&lt;br /&gt;    @ResourceDependency(library = "js", name = "tooltip/tooltip.js")&lt;br /&gt;})&lt;br /&gt;public class Tooltip extends org.primefaces.component.tooltip.Tooltip&lt;br /&gt;{&lt;br /&gt;    public java.lang.String getTargetPosition() {&lt;br /&gt;        return (java.lang.String) getStateHelper().eval(PropertyKeys.targetPosition, "bottom right");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public java.lang.String getPosition() {&lt;br /&gt;        return (java.lang.String) getStateHelper().eval(PropertyKeys.position, "top left");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public java.lang.String getShowEffect() {&lt;br /&gt;        return (java.lang.String) getStateHelper().eval(PropertyKeys.showEffect, "fadeIn");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public java.lang.String getHideEffect() {&lt;br /&gt;        return (java.lang.String) getStateHelper().eval(PropertyKeys.hideEffect, "fadeOut");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public java.lang.String getShowEvent() {&lt;br /&gt;        return (java.lang.String) getStateHelper().eval(PropertyKeys.showEvent, "mouseenter");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public java.lang.String getHideEvent() {&lt;br /&gt;        return (java.lang.String) getStateHelper().eval(PropertyKeys.hideEvent, "mouseleave");&lt;br /&gt;    }    &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: orange;"&gt;jquery.qtip.js&lt;/span&gt; is a new qTip script placed under the folder &lt;span style="color: orange;"&gt;webapp/resources/js/tooltip&lt;/span&gt; and the &lt;span style="color: orange;"&gt;tooltip.js&lt;/span&gt; is our one. In the &lt;span style="color: orange;"&gt;tooltip.js&lt;/span&gt; I use the jQuery &lt;span style="color: orange;"&gt;.live()&lt;/span&gt; method playing together with qTip2. This method allows us to easily add qTips to certain elements on a page, even when updating the DOM and adding new elements.&lt;br /&gt;&lt;pre class="brush:js"&gt;PrimeFaces.widget.Tooltip = function(cfg) {&lt;br /&gt;    this.cfg = cfg;&lt;br /&gt;    var _self = this;&lt;br /&gt;&lt;br /&gt;    if (this.cfg.global) {&lt;br /&gt;        // Bind the qTip within the event handler&lt;br /&gt;        jQuery('*[title]').live(this.cfg.show.event, function(event) {&lt;br /&gt;            var extCfg = _self.cfg;&lt;br /&gt;            // Show the tooltip as soon as it's bound&lt;br /&gt;            extCfg.show.ready = true;&lt;br /&gt;            jQuery(this).qtip(extCfg, event);&lt;br /&gt;        });&lt;br /&gt;    } else {&lt;br /&gt;        jQuery(PrimeFaces.escapeClientId(this.cfg.forComponent)).qtip(this.cfg);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// make tooltip theme aware&lt;br /&gt;jQuery.fn.qtip.defaults.style.widget = true;&lt;br /&gt;jQuery.fn.qtip.defaults.style.classes = "ui-tooltip-rounded ui-tooltip-shadow";&lt;br /&gt;&lt;/pre&gt;jQuery ThemeRoller integration is done by the last two lines. The last step is to extend PrimeFaces's &lt;span style="color: orange;"&gt;TooltipRenderer&lt;/span&gt; (because tooltip API has been changed) and register then all stuff in the faces-config.xml&lt;br /&gt;&lt;pre class="brush:java"&gt;public class TooltipRenderer extends org.primefaces.component.tooltip.TooltipRenderer&lt;br /&gt;{&lt;br /&gt;    public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {&lt;br /&gt;        Tooltip tooltip = (Tooltip) component;&lt;br /&gt;&lt;br /&gt;        // dummy markup for ajax update (not really necessary)&lt;br /&gt;        ResponseWriter writer = facesContext.getResponseWriter();&lt;br /&gt;        writer.startElement("span", tooltip);&lt;br /&gt;        writer.writeAttribute("id", tooltip.getClientId(facesContext), "id");&lt;br /&gt;        writer.endElement("span");&lt;br /&gt;&lt;br /&gt;        encodeScript(facesContext, tooltip);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected void encodeScript(FacesContext facesContext, org.primefaces.component.tooltip.Tooltip tp)&lt;br /&gt;        throws IOException {&lt;br /&gt;        Tooltip tooltip = (Tooltip) tp;&lt;br /&gt;        ResponseWriter writer = facesContext.getResponseWriter();&lt;br /&gt;        boolean global = tooltip.isGlobal();&lt;br /&gt;        String owner = getTarget(facesContext, tooltip);&lt;br /&gt;&lt;br /&gt;        writer.startElement("script", null);&lt;br /&gt;        writer.writeAttribute("type", "text/javascript", null);&lt;br /&gt;&lt;br /&gt;        writer.write("jQuery(function() {");&lt;br /&gt;        writer.write(tooltip.resolveWidgetVar() + " = new PrimeFaces.widget.Tooltip({");&lt;br /&gt;        writer.write("global:" + global);&lt;br /&gt;&lt;br /&gt;        if (!global) {&lt;br /&gt;            writer.write(",forComponent:'" + owner + "'");&lt;br /&gt;            writer.write(",content:'");&lt;br /&gt;            if (tooltip.getValue() == null) {&lt;br /&gt;                renderChildren(facesContext, tooltip);&lt;br /&gt;            } else {&lt;br /&gt;                writer.write(ComponentUtils.getStringValueToRender(facesContext, tooltip).replaceAll("'", "\\\\'"));&lt;br /&gt;            }&lt;br /&gt;            writer.write("'");&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        writer.write(",show:{event:'" + tooltip.getShowEvent() + "',delay:" + tooltip.getShowDelay() + &lt;br /&gt;            ",effect:function(){jQuery(this)." + tooltip.getShowEffect() + "(" + tooltip.getShowEffectLength() + ");}}");&lt;br /&gt;        writer.write(",hide:{event:'" + tooltip.getHideEvent() + "',delay:" + tooltip.getHideDelay() + &lt;br /&gt;            ",effect:function(){jQuery(this)." + tooltip.getHideEffect() + "(" + tooltip.getHideEffectLength() + ");}}");&lt;br /&gt;        writer.write(",position: {");&lt;br /&gt;        String container = owner == null ? &lt;br /&gt;            "jQuery(document.body)" : "jQuery(PrimeFaces.escapeClientId('" + owner + "')).parent()";&lt;br /&gt;        writer.write("container:" + container);&lt;br /&gt;        writer.write(",at:'" + tooltip.getTargetPosition() + "'");&lt;br /&gt;        writer.write(",my:'" + tooltip.getPosition() + "'");&lt;br /&gt;        writer.write("}});});");&lt;br /&gt;&lt;br /&gt;        writer.endElement("script");&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Have much fun! In one of my next post I will explain how to show a nice tooltip attached to the PrimeFaces &lt;span style="color: orange;"&gt;Autocomplete&lt;/span&gt; component if user input disallowed characters.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Edit:&lt;/u&gt; I think a binding with namespace would be better to avoid collisions. Furthermore, a call of &lt;span style="color: orange;"&gt;.die()&lt;/span&gt; before &lt;span style="color: orange;"&gt;.live()&lt;/span&gt; is necessary in order to prevent miltiply binding of the same event if the tooltip gets updated via ajax. The same is for non global tooltips&lt;br /&gt;&lt;pre class="brush:js"&gt;jQuery('*[title]').die(this.cfg.show.event + ".tooltip").live(this.cfg.show.event + ".tooltip", ...&lt;br /&gt;    ...&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;... in else ...&lt;br /&gt;&lt;br /&gt;// delete previous tooltip to support ajax updates and create a new one&lt;br /&gt;jQuery(PrimeFaces.escapeClientId(this.cfg.forComponent)).qtip('destroy').qtip(this.cfg);&lt;br /&gt;&lt;/pre&gt;The container element which the tooltip is appended to should be always &lt;span style="color: orange;"&gt;document.body&lt;/span&gt; in order to play nice with layout, datatable, etc. Changes in &lt;span style="color: orange;"&gt;TooltipRenderer.java&lt;/span&gt;:&lt;br /&gt;&lt;pre class="brush:java"&gt;writer.write("container:jQuery(document.body)");&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-1081142321944216222?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/1081142321944216222/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/06/global-tooltips-with-primefaces-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1081142321944216222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1081142321944216222'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/06/global-tooltips-with-primefaces-and.html' title='Global tooltips with PrimeFaces and qTip2'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-7841384421122204071</id><published>2011-06-08T12:41:00.000-07:00</published><updated>2011-06-08T12:41:56.101-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='PrimeFaces'/><category scheme='http://www.blogger.com/atom/ns#' term='Validation'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>Client-side validation with jQuery validation plugin. Advanced examples.</title><content type='html'>&lt;a href="http://ovaraksin.blogspot.com/2011/06/client-side-validation-with-jquery.html"&gt;In the last post&lt;/a&gt; I covered the basics of the great &lt;a href="http://docs.jquery.com/Plugins/Validation"&gt;jQuery validation plugin&lt;/a&gt; - state-of-the-art for client-side validation. I'm going to show now an advanced example how to write validation rules, own validation methods and put all together. I'm writing a collaborative whiteboard just now and needed two dialogs placed in the same HTML form. My task were: &lt;br /&gt;&lt;br /&gt;&lt;b&gt;1)&lt;/b&gt; Write a dialog to input a valid image URL, image width and height. This dialog looks as follows&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-zKRLf0ONlOE/Te_M5b4lNUI/AAAAAAAAAEU/aWtpTA3EI4w/s1600/dialogValidation1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-zKRLf0ONlOE/Te_M5b4lNUI/AAAAAAAAAEU/aWtpTA3EI4w/s1600/dialogValidation1.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;and was written in JSF (PrimeFaces) as&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;p:dialog id=&amp;quot;dialogInputImage&amp;quot; header=&amp;quot;Input image URL&amp;quot; resizable=&amp;quot;false&amp;quot; closable=&amp;quot;true&amp;quot; modal=&amp;quot;true&amp;quot; styleClass=&amp;quot;validatable&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;ul id=&amp;quot;errorImageUl&amp;quot; class=&amp;quot;errormsg&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;h:panelGrid id=&amp;quot;dlgImageGrid&amp;quot; columns=&amp;quot;2&amp;quot; columnClasses=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;h:outputLabel value=&amp;quot;Image URL&amp;quot; for=&amp;quot;inputUrl&amp;quot;/&amp;gt;&lt;br /&gt;        &amp;lt;p:inputText id=&amp;quot;inputUrl&amp;quot;/&amp;gt;&lt;br /&gt;        &amp;lt;h:outputLabel value=&amp;quot;Image width (px)&amp;quot; for=&amp;quot;imgWidth&amp;quot;/&amp;gt;&lt;br /&gt;        &amp;lt;h:panelGroup&amp;gt;&lt;br /&gt;            &amp;lt;p:inputText id=&amp;quot;imgWidth&amp;quot; maxlength=&amp;quot;4&amp;quot;/&amp;gt;&lt;br /&gt;            &amp;lt;h:outputLabel value=&amp;quot;Image height (px)&amp;quot; for=&amp;quot;imgHeight&amp;quot; style=&amp;quot;margin: 0 10px 0 10px;&amp;quot;/&amp;gt;&lt;br /&gt;            &amp;lt;p:inputText id=&amp;quot;imgHeight&amp;quot; maxlength=&amp;quot;4&amp;quot;/&amp;gt;&lt;br /&gt;        &amp;lt;/h:panelGroup&amp;gt;&lt;br /&gt;    &amp;lt;/h:panelGrid&amp;gt;&lt;br /&gt;&amp;lt;/p:dialog&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;2)&lt;/b&gt; Write a second dialog with input fields for whiteboard width and height. This dialog looks as follows&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-BpV9TV51wrM/Te_NV8wRTpI/AAAAAAAAAEY/ixEeDwzd2r0/s1600/dialogValidation3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-BpV9TV51wrM/Te_NV8wRTpI/AAAAAAAAAEY/ixEeDwzd2r0/s1600/dialogValidation3.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;and was written in JSF (PrimeFaces) as&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;p:dialog id=&amp;quot;dialogResize&amp;quot; header=&amp;quot;Resize Whiteboard&amp;quot; resizable=&amp;quot;false&amp;quot; closable=&amp;quot;true&amp;quot; modal=&amp;quot;true&amp;quot; styleClass=&amp;quot;validatable&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;ul id=&amp;quot;errorResizeUl&amp;quot; class=&amp;quot;errormsg&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;h:panelGrid id=&amp;quot;dlgResizeGrid&amp;quot; columns=&amp;quot;4&amp;quot; columnClasses=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;h:outputLabel value=&amp;quot;Whiteboard width (px)&amp;quot; for=&amp;quot;wbWidth&amp;quot;/&amp;gt;&lt;br /&gt;        &amp;lt;p:inputText id=&amp;quot;wbWidth&amp;quot; maxlength=&amp;quot;4&amp;quot;/&amp;gt;&lt;br /&gt;        &amp;lt;h:outputLabel value=&amp;quot;Whiteboard height (px)&amp;quot; for=&amp;quot;wbHeight&amp;quot;/&amp;gt;&lt;br /&gt;        &amp;lt;p:inputText id=&amp;quot;wbHeight&amp;quot; maxlength=&amp;quot;4&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;/h:panelGrid&amp;gt;&lt;br /&gt;&amp;lt;/p:dialog&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;3)&lt;/b&gt; Validation requirements:&lt;br /&gt;&lt;br /&gt;&lt;u&gt;First dialog.&lt;/u&gt;&lt;br /&gt;- If nothing was input (all fields are empty) ==&amp;gt; no validation for all fields.&lt;br /&gt;- If the URL field is empty ==&amp;gt; no validation for all fields.&lt;br /&gt;- If the URL field is not empty ==&amp;gt; check if the URL is valid and input image width / height are positive digits (greater than 0).&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Second dialog.&lt;/u&gt;&lt;br /&gt;- Always check input width and height which should be positive digits (greater than 0).&lt;br /&gt;&lt;br /&gt;Furthermore, error messages should be groupped. I use "&lt;span style="color: orange;"&gt;errorPlacement&lt;/span&gt;" option for this. We need an error container to play nice with "&lt;span style="color: orange;"&gt;errorPlacement&lt;/span&gt;". Therefore, I defined an error container in each dialog by &lt;span style="color: orange;"&gt;UL&lt;/span&gt; element which will contain &lt;span style="color: orange;"&gt;LI&lt;/span&gt; elements if any errors occur.&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;ul id="..." class="errormsg"/&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;Let me show the JavaScript part now. Comments help to understand the logic behind my code. The code should be placed after all &lt;span style="color: orange;"&gt;p:dialog&lt;/span&gt; tags&lt;br /&gt;&lt;pre class="brush:js"&gt;jQuery(function() {&lt;br /&gt;    // add a new validation method to validate image width / height&lt;br /&gt;    jQuery.validator.addMethod("imageSize", function(value, element, param) {&lt;br /&gt;        // check parameter "#inputUrl:filled" (see validate(...) method below) &lt;br /&gt;        if (jQuery.find(param).length &amp;lt; 1) {&lt;br /&gt;            return true;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // use built-in "digits" validator and check if digits are positive&lt;br /&gt;        return !this.optional(element) &amp;amp;&amp;amp; jQuery.validator.methods['digits'].call(this, value, element) &amp;amp;&amp;amp; parseInt(value) &amp;gt; 0;&lt;br /&gt;    }, "Please enter a valid image size (only positive digits are allowed).");&lt;br /&gt;&lt;br /&gt;    // create an object with rules for convenience (using in validate(...))&lt;br /&gt;    var dimensionRules = {&lt;br /&gt;        required: true,&lt;br /&gt;        digits: true,&lt;br /&gt;        min: 1&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    // create a validator with rules for all dialog fields&lt;br /&gt;    dialogValidator = jQuery("#mainForm").validate({&lt;br /&gt;        // validation is on demand ==&amp;gt; set onfocusout and onkeyup validation to false&lt;br /&gt;        onfocusout: false,&lt;br /&gt;        onkeyup: false,&lt;br /&gt;        errorPlacement: function(label, elem) {&lt;br /&gt;            elem.closest(".validatable").find(".errormsg").append(label);&lt;br /&gt;        },&lt;br /&gt;        wrapper: "li",&lt;br /&gt;        rules: {&lt;br /&gt;            inputUrl: {&lt;br /&gt;                url: true&lt;br /&gt;            },&lt;br /&gt;            imgWidth: {&lt;br /&gt;                // validation of image size depends on input URL - validate size for not empty URL only&lt;br /&gt;                imageSize: "#inputUrl:filled"&lt;br /&gt;            },&lt;br /&gt;            imgHeight: {&lt;br /&gt;                // validation of image size depends on input URL - validate size for not empty URL only&lt;br /&gt;                imageSize: "#inputUrl:filled"&lt;br /&gt;            },&lt;br /&gt;            wbWidth: dimensionRules,&lt;br /&gt;            wbHeight: dimensionRules&lt;br /&gt;        },&lt;br /&gt;        messages: {&lt;br /&gt;            // define validation messages&lt;br /&gt;            inputUrl: "Please enter a valid image URL.",&lt;br /&gt;            imgWidth: "Please enter a valid image width (only positive digits are allowed).",&lt;br /&gt;            imgHeight: "Please enter a valid image height (only positive digits are allowed).",&lt;br /&gt;            wbWidth: "Please enter a valid whiteboard width (only positive digits are allowed).",&lt;br /&gt;            wbHeight: "Please enter a valid whiteboard height (only positive digits are allowed)."&lt;br /&gt;        }&lt;br /&gt;    });&lt;br /&gt;&lt;br /&gt;    // configure the first dialog&lt;br /&gt;    jQuery("#dialogInputImage").dialog("option", "buttons", {&lt;br /&gt;        "Accept": function() {&lt;br /&gt;            // validate all fields if user click on the "Accept" button&lt;br /&gt;            var isValid1 = dialogValidator.element("#inputUrl");&lt;br /&gt;            var isValid2 = dialogValidator.element("#imgWidth");&lt;br /&gt;            var isValid3 = dialogValidator.element("#imgHeight");&lt;br /&gt;&lt;br /&gt;            if ((typeof isValid1 !== 'undefined' &amp;amp;&amp;amp; !isValid1) || (typeof isValid2 !== 'undefined' &amp;amp;&amp;amp; !isValid2) ||&lt;br /&gt;               (typeof isValid3 !== 'undefined' &amp;amp;&amp;amp; !isValid3)) {&lt;br /&gt;                // validation failed&lt;br /&gt;                return false;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            // do something ...&lt;br /&gt;        },&lt;br /&gt;        "Close": function() {&lt;br /&gt;            jQuery(this).dialog("close");&lt;br /&gt;        }&lt;br /&gt;    }).bind("dialogclose", function(event, ui) {&lt;br /&gt;        // reset input&lt;br /&gt;        jQuery(this).find("#inputUrl").val('');&lt;br /&gt;        // clean up validation messages&lt;br /&gt;        jQuery("#errorImageUl").html('');&lt;br /&gt;    });&lt;br /&gt;&lt;br /&gt;    // configure the second dialog&lt;br /&gt;    jQuery("#dialogResize").dialog("option", "buttons", {&lt;br /&gt;        "Accept": function() {&lt;br /&gt;            // validate all fields if user click on the "Accept" button&lt;br /&gt;            var isValid1 = dialogValidator.element("#wbWidth");&lt;br /&gt;            var isValid2 = dialogValidator.element("#wbHeight");&lt;br /&gt;&lt;br /&gt;            if ((typeof isValid1 !== 'undefined' &amp;amp;&amp;amp; !isValid1) || (typeof isValid2 !== 'undefined' &amp;amp;&amp;amp; !isValid2)) {&lt;br /&gt;                // validation failed&lt;br /&gt;                return false;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            // do something ...&lt;br /&gt;&lt;br /&gt;            jq.dialog("close");&lt;br /&gt;            &lt;br /&gt;            // do something ...&lt;br /&gt;        },&lt;br /&gt;        "Close": function() {&lt;br /&gt;            jQuery(this).dialog("close");&lt;br /&gt;        }&lt;br /&gt;    }).bind("dialogclose", function(event, ui) {&lt;br /&gt;        // clean up validation messages&lt;br /&gt;        jQuery("#errorResizeUl").html('');&lt;br /&gt;    });&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;Validation looks now as follows&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-X1RStoD7he0/Te_O0O6bTaI/AAAAAAAAAEc/Zwv2uOjbP4Y/s1600/dialogValidation2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-X1RStoD7he0/Te_O0O6bTaI/AAAAAAAAAEc/Zwv2uOjbP4Y/s1600/dialogValidation2.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-s1zrq815HOo/Te_O7YZuc4I/AAAAAAAAAEg/tJqX2q1HprA/s1600/dialogValidation4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-s1zrq815HOo/Te_O7YZuc4I/AAAAAAAAAEg/tJqX2q1HprA/s1600/dialogValidation4.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&amp;nbsp;In fact I already implemented partially client-side validation as JSF components ;-).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-7841384421122204071?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/7841384421122204071/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/06/client-side-validation-with-jquery_08.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7841384421122204071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7841384421122204071'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/06/client-side-validation-with-jquery_08.html' title='Client-side validation with jQuery validation plugin. Advanced examples.'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-zKRLf0ONlOE/Te_M5b4lNUI/AAAAAAAAAEU/aWtpTA3EI4w/s72-c/dialogValidation1.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-4303724247443287424</id><published>2011-06-04T08:30:00.000-07:00</published><updated>2011-06-04T08:39:42.939-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='PrimeFaces'/><category scheme='http://www.blogger.com/atom/ns#' term='Validation'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>Client-side validation with jQuery validation plugin. Basic concepts.</title><content type='html'>&lt;a href="http://docs.jquery.com/Plugins/Validation"&gt;jQuery validation plugin&lt;/a&gt; is my favorite framework for client-side validation. I'm surprised more and more about its power and flexibility. Before I start to describe my recently task for client-side validation I would like to say few words how this plugin works at all. jQuery validation plugin has a predefined set of validation methods for required fields, emails, URLs, credit card, numbers, dates, etc. All bundled methods come with default error messages in english and translations into 32+ languages. By default, error messages are displayed after the invalid element, but this is also customizable. It is also possible to put them into an error container at some other places and show them bundled all together. Desired validation methods can be specified in two ways:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1)&lt;/b&gt; By HTML "class" attribute.&lt;br /&gt;&lt;b&gt;2)&lt;/b&gt; By rules in JavaScript.&lt;br /&gt;&lt;br /&gt;The first way is simple. Assume, you have a form with Id "&lt;span style="color: orange;"&gt;registerForm&lt;/span&gt;" containing fields "&lt;span style="color: orange;"&gt;Name&lt;/span&gt;" and "&lt;span style="color: orange;"&gt;E-mail&lt;/span&gt;". Both fields should be required. In additional, the field "&lt;span style="color: orange;"&gt;Name&lt;/span&gt;" requires minimum 3 letters and the field "&lt;span style="color: orange;"&gt;E-mail&lt;/span&gt;" accepts only valid e-mail inputs.&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;lt;form id="registerForm" method="get" action="..."&amp;gt;&lt;br /&gt;    &amp;lt;label for="name"&amp;gt;Name&amp;lt;/label&amp;gt;&lt;br /&gt;    &amp;lt;input id="name" name="name" size="25" class="required" minlength="3" /&amp;gt;&lt;br /&gt;    &amp;lt;label for="email"&amp;gt;E-Mail&amp;lt;/label&amp;gt;&lt;br /&gt;    &amp;lt;input id="email" name="email" size="25" class="required email" /&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&lt;/pre&gt;Validation methods are specified here by "&lt;span style="color: orange;"&gt;class&lt;/span&gt;" attributes. The form can be validated now by the call&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;jQuery("#registerForm").validate();&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;How does this plugin behave? By default, forms are validated on submit, triggered by the user clicking the submit button or pressing enter when a form input is focused. There is also validation on single elements on demand.&lt;br /&gt;&lt;pre class="brush:js"&gt;var validator;&lt;br /&gt;&lt;br /&gt;jQuery(document).ready(function(){&lt;br /&gt;     validator = jQuery("#registerForm").validate();&lt;br /&gt;     ...&lt;br /&gt;     doSomething();&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;function doSomething() {&lt;br /&gt;    var isNameValid = validator.element("#name");&lt;br /&gt;    if (isNameValid) {&lt;br /&gt;        // do something&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The call &lt;span style="color: orange;"&gt;validator.element("#name")&lt;/span&gt; above validates a single field "&lt;span style="color: orange;"&gt;Name&lt;/span&gt;" and returns true if it is valid, false otherwise.&lt;br /&gt;&lt;br /&gt;Before submitting the form for the first time the validation is lazy. The user can tab through fields without getting annoying messages. He has a chance to correct input values. Once a field was marked invalid, it is eagerly validated. The plugin validates on keyup if the user types something. When the user enters something invalid into a valid field, it is also validated when the field loses focus (onblur). In addition, a field can be highlighted as invalid. As soon as the user entered the necessary value, the error message is removed.&lt;br /&gt;&lt;br /&gt;I prefer the second way - validation by rules definitions via JavaScript. This is more flexible and leaves nothing to be desired - there are many configuration parameters. Rules and messages can be configured in the &lt;span style="color: orange;"&gt;validate(...)&lt;/span&gt; method. Each rule specifies Id of the field to be validated and desired validation methods for this field. &lt;br /&gt;&lt;pre class="brush:js"&gt;jQuery(&amp;quot;#registerForm&amp;quot;).validate({&lt;br /&gt;    rules: {&lt;br /&gt;        name: {&lt;br /&gt;            required: true,&lt;br /&gt;            minlength: 3&lt;br /&gt;        },&lt;br /&gt;        email: {&lt;br /&gt;            required: true,&lt;br /&gt;            email: true&lt;br /&gt;        }&lt;br /&gt;    },&lt;br /&gt;    messages: {&lt;br /&gt;        name: &amp;quot;Please enter a valid name.&amp;quot;,&lt;br /&gt;        email: &amp;quot;Please enter a valid e-mail.&amp;quot;&lt;br /&gt;    }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;Rules can be added dynamically too after &lt;span style="color: orange;"&gt;validate()&lt;/span&gt; was called. Like this one for the field with Id "&lt;span style="color: orange;"&gt;name&lt;/span&gt;" above.&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;jQuery("#name").rules("add", {minlength: 3});&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;Validation methods can be grouped as one. For example if you want to group all three built-in validation methods "&lt;span style="color: orange;"&gt;required&lt;/span&gt;", "&lt;span style="color: orange;"&gt;date&lt;/span&gt;" and "&lt;span style="color: orange;"&gt;dateRange&lt;/span&gt;", you can write&lt;br /&gt;&lt;pre class="brush:js"&gt;jQuery.validator.addClassRules({&lt;br /&gt;    requiredDateRange: {required:true, date:true, dateRange:true}&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;The new validation method is called now "&lt;span style="color: orange;"&gt;requiredDateRange&lt;/span&gt;". Another nice feature - overwriting of default messages. Example for "&lt;span style="color: orange;"&gt;required&lt;/span&gt;" and "&lt;span style="color: orange;"&gt;date&lt;/span&gt;" validations:&lt;br /&gt;&lt;pre class="brush:js"&gt;jQuery.extend(jQuery.validator.messages, {&lt;br /&gt;    required: "These fields are required",&lt;br /&gt;    date: "Please specify valid dates"&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;Last but not least - adding of new validation methods by&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;jQuery.validator.addMethod(name, method, [message]);&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;In the next post I will show an example for &lt;span style="color: orange;"&gt;jQuery.validator.addMethod&lt;/span&gt; and more other advanced tricks. Stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-4303724247443287424?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/4303724247443287424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/06/client-side-validation-with-jquery.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/4303724247443287424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/4303724247443287424'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/06/client-side-validation-with-jquery.html' title='Client-side validation with jQuery validation plugin. Basic concepts.'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-862368149695375213</id><published>2011-05-29T12:19:00.000-07:00</published><updated>2011-05-29T12:26:03.601-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JSON'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Test'/><title type='text'>Testing client-server communication with Java Scripting API</title><content type='html'>I would like to share my best practice for client- and server-side testing with &lt;a href="http://download.oracle.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html"&gt;Java Scripting API&lt;/a&gt; introduced in Java SE 6. As example I want to test simultaneous JSON serialization / deserialization on both sides. I'm going to use &lt;a href="https://github.com/douglascrockford/JSON-js"&gt;json2&lt;/a&gt; from Douglas Crockford on client-side and &lt;a href="http://code.google.com/p/google-gson/"&gt;Gson&lt;/a&gt; on server-side. I want to utilize the class &lt;span style="color: orange;"&gt;Circle&lt;/span&gt; from my &lt;a href="http://ovaraksin.blogspot.com/2011/05/json-with-gson-and-abstract-classes.html"&gt;previous post&lt;/a&gt; and write JUnit tests for its serialization / deserialization. At first we need to implement the same interface by Java and JavaScript. It's convenient to implement an Java interface by script functions or methods. By using interfaces we can avoid having to use the &lt;span style="color: orange;"&gt;javax.script &lt;/span&gt;API in many places.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;JsonProvide.java&lt;/u&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;public interface JsonProvider&lt;br /&gt;{&lt;br /&gt;    public Object fromJson(String json);&lt;br /&gt;&lt;br /&gt;    public String toJson(Object object);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: orange;"&gt;JsonProvider&lt;/span&gt; is an interface which is used later to access correspondent JavaScript methods.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;jsonTest.js&lt;/u&gt;&lt;br /&gt;&lt;pre class="brush:js"&gt;var jsonProvider = new Object();&lt;br /&gt;&lt;br /&gt;// produces an JavaScript object or array from an JSON text.&lt;br /&gt;jsonProvider.fromJson = function(json) {&lt;br /&gt;    var obj = JSON.parse(json);&lt;br /&gt;    return makeTestable(obj);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// produces an JSON text from an JavaScript object or array&lt;br /&gt;jsonProvider.toJson = function(object) {&lt;br /&gt;    var obj = makeTestable(object);&lt;br /&gt;    return JSON.stringify(obj);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;function makeTestable(obj) {&lt;br /&gt;    obj.getValue = function(property) {&lt;br /&gt;        return this[property];&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    return obj;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Test object&lt;br /&gt;var circle = {&lt;br /&gt;    uuid: "567e6162-3b6f-4ae2-a171-2470b63dff00",&lt;br /&gt;    x: 10,&lt;br /&gt;    y: 20,&lt;br /&gt;    movedToFront: true,&lt;br /&gt;    rotationDegree: 90,&lt;br /&gt;    radius: 50,&lt;br /&gt;    backgroundColor: "#FF0000",&lt;br /&gt;    borderColor: "#DDDDDD",&lt;br /&gt;    borderWidth: 1,&lt;br /&gt;    borderStyle: "-",&lt;br /&gt;    backgroundOpacity: 1.0,&lt;br /&gt;    borderOpacity: 0.5,&lt;br /&gt;    scaleFactor: 1.2&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;There are two methods &lt;span style="color: orange;"&gt;fromJson&lt;/span&gt; / &lt;span style="color: orange;"&gt;toJson&lt;/span&gt; and a helper function &lt;span style="color: orange;"&gt;makeTestable&lt;/span&gt; in order to get any value of JavaScript objects from Java. The test object in JavaScript is called &lt;span style="color: orange;"&gt;circle&lt;/span&gt;. The corresponding Java class is called &lt;span style="color: orange;"&gt;Circle&lt;/span&gt; and has the same fields with getter / setter. We can write an JUnit test now.&lt;br /&gt;&lt;pre class="brush:java"&gt;import com.google.gson.Gson;&lt;br /&gt;import com.googlecode.whiteboard.model.Circle;&lt;br /&gt;import org.apache.commons.beanutils.PropertyUtils;&lt;br /&gt;import org.junit.AfterClass;&lt;br /&gt;import org.junit.Assert;&lt;br /&gt;import org.junit.BeforeClass;&lt;br /&gt;import org.junit.Test;&lt;br /&gt;&lt;br /&gt;import javax.script.Invocable;&lt;br /&gt;import javax.script.ScriptEngine;&lt;br /&gt;import javax.script.ScriptEngineManager;&lt;br /&gt;import javax.script.ScriptException;&lt;br /&gt;import java.io.FileNotFoundException;&lt;br /&gt;import java.util.Map;&lt;br /&gt;import java.util.Set;&lt;br /&gt;import java.util.UUID;&lt;br /&gt;&lt;br /&gt;public class JsonTest&lt;br /&gt;{&lt;br /&gt;    private static Gson gson;&lt;br /&gt;    private static ScriptEngine engine;&lt;br /&gt;    private static JsonProvider jsonProvider;&lt;br /&gt;&lt;br /&gt;    @BeforeClass&lt;br /&gt;    public static void runBeforeClass() {&lt;br /&gt;        // create Gson&lt;br /&gt;        GsonBuilder gsonBilder = new GsonBuilder();&lt;br /&gt;        gson = gsonBilder.serializeNulls().create();&lt;br /&gt;&lt;br /&gt;        // create a script engine manager&lt;br /&gt;        ScriptEngineManager factory = new ScriptEngineManager();&lt;br /&gt;        // create JavaScript engine&lt;br /&gt;        engine = factory.getEngineByName("JavaScript");&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            // evaluate JavaScript code from the json2 library and the test file&lt;br /&gt;            engine.eval(new java.io.FileReader("src/main/webapp/resources/js/json2-min.js"));&lt;br /&gt;            engine.eval(new java.io.FileReader("src/test/resources/js/jsonTest.js"));&lt;br /&gt;&lt;br /&gt;            // get an implementation instance of the interface JsonProvider from the JavaScript engine,&lt;br /&gt;            // all interface's methods are implemented by script methods of JavaScript object jsonProvider&lt;br /&gt;            Invocable inv = (Invocable) engine;&lt;br /&gt;            jsonProvider = inv.getInterface(engine.get("jsonProvider"), JsonProvider.class);&lt;br /&gt;        } catch (ScriptException e) {&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;        } catch (FileNotFoundException e) {&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @AfterClass&lt;br /&gt;    public static void runAfterClass() {&lt;br /&gt;        gson = null;&lt;br /&gt;        jsonProvider = null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Test&lt;br /&gt;    public void JavaScript2Java() {&lt;br /&gt;        // get JavaScript object&lt;br /&gt;        Object circle1 = engine.get("circle");&lt;br /&gt;&lt;br /&gt;        // client-side: make JSON text from JavaScript object&lt;br /&gt;        String json = jsonProvider.toJson(circle1);&lt;br /&gt;&lt;br /&gt;        // server-side: convert JSON text to Java object&lt;br /&gt;        Circle circle2 = gson.fromJson(json, Circle.class);&lt;br /&gt;&lt;br /&gt;        // compare two objects&lt;br /&gt;        testEquivalence(circle2, circle1);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Test&lt;br /&gt;    public void Java2JavaScript() {&lt;br /&gt;        // create Java object&lt;br /&gt;        Circle circle1 = new Circle();&lt;br /&gt;        circle1.setUuid(UUID.randomUUID().toString());&lt;br /&gt;        circle1.setX(100);&lt;br /&gt;        circle1.setY(100);&lt;br /&gt;        circle1.setMovedToFront(false);&lt;br /&gt;        circle1.setRotationDegree(0);&lt;br /&gt;        circle1.setRadius(250);&lt;br /&gt;        circle1.setBackgroundColor("#FFFFFF");&lt;br /&gt;        circle1.setBorderColor("#000000");&lt;br /&gt;        circle1.setBorderWidth(3);&lt;br /&gt;        circle1.setBorderStyle(".");&lt;br /&gt;        circle1.setBackgroundOpacity(0.2);&lt;br /&gt;        circle1.setBorderOpacity(0.8);&lt;br /&gt;        circle1.setScaleFactor(1.0);&lt;br /&gt;&lt;br /&gt;        // server-side: convert Java object to JSON text&lt;br /&gt;        String json = gson.toJson(circle1);&lt;br /&gt;&lt;br /&gt;        // client-side: make JavaScript object from JSON text&lt;br /&gt;        Object circle2 = jsonProvider.fromJson(json);&lt;br /&gt;&lt;br /&gt;        // compare two objects&lt;br /&gt;        testEquivalence(circle1, circle2);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @SuppressWarnings("unchecked")&lt;br /&gt;    private void testEquivalence(Object obj1, Object obj2) {&lt;br /&gt;        try {&lt;br /&gt;            Map&amp;lt;String, Object&amp;gt; map = PropertyUtils.describe(obj1);&lt;br /&gt;            Set&amp;lt;String&amp;gt; fields = map.keySet();&lt;br /&gt;            Invocable inv = (Invocable) engine;&lt;br /&gt;&lt;br /&gt;            for (String key : fields) {&lt;br /&gt;                Object value1 = map.get(key);&lt;br /&gt;                if (!key.equals("class")) {&lt;br /&gt;                    Object value2 = inv.invokeMethod(obj2, "getValue", key);&lt;br /&gt;                    if (value1 instanceof Number &amp;amp;&amp;amp; !(value1 instanceof Double)) {&lt;br /&gt;                        // JS number is always converted to Java double ==&amp;gt; only doubles can be compared,&lt;br /&gt;                        // see http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html&lt;br /&gt;                        value1 = new Double(value1.toString());&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                    Assert.assertEquals("Value of property '" + key + "' was wrong converted", value2, value1);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        } catch (Exception e) {&lt;br /&gt;            throw new IllegalStateException("Equivalence test of two objects failed!", e);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;I create a &lt;span style="color: orange;"&gt;Gson&lt;/span&gt; and a &lt;span style="color: orange;"&gt;ScriptEngine&lt;/span&gt; instances in the method &lt;span style="color: orange;"&gt;runBeforeClass()&lt;/span&gt; and load all needed scripts into the &lt;span style="color: orange;"&gt;ScriptEngine&lt;/span&gt;. After that I get an implementation instance of the interface &lt;span style="color: orange;"&gt;JsonProvider&lt;/span&gt; from the JavaScript engine. Now I'm able to call JavaScript methods from my &lt;span style="color: orange;"&gt;JsonProvider&lt;/span&gt; implementation. There are two tests:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;@Test public void JavaScript2Java()&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I test here the use case if an JavaScript object (&lt;span style="color: orange;"&gt;circle&lt;/span&gt;) gets converted to an JSON text, sent to the server and converted there to an Java object (&lt;span style="color: orange;"&gt;Circle&lt;/span&gt;). The original JavaScript object and the result Java object are compared afterwards.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;@Test public void Java2JavaScript()&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I test here the use case if a created Java object (&lt;span style="color: orange;"&gt;Circle&lt;/span&gt;) gets converted to an JSON text, sent to the client and converted there to an JavaScript object (&lt;span style="color: orange;"&gt;circle&lt;/span&gt;). The objects are compared to ensure their equivalence.&lt;br /&gt;&lt;br /&gt;You can also use "JavaScript to Java Communication" with Java Scripting API and access Java classes, objects and methods from JavaScript. Pretty cool.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-862368149695375213?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/862368149695375213/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/05/testing-client-server-communication.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/862368149695375213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/862368149695375213'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/05/testing-client-server-communication.html' title='Testing client-server communication with Java Scripting API'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-5937159696596277406</id><published>2011-05-26T05:12:00.000-07:00</published><updated>2011-06-01T02:50:20.157-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='PrimeFaces'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>Auto sized jQuery UI dialogs and PrimeFaces</title><content type='html'>&lt;a href="http://jqueryui.com/demos/dialog/"&gt;jQuery (modal) dialog&lt;/a&gt; causes some problems in Internet Explorer like scrollbars on page and not working auto width. See e.g. tickets &lt;a href="http://bugs.jqueryui.com/ticket/3623"&gt;http://bugs.jqueryui.com/ticket/3623&lt;/a&gt; and &lt;a href="http://bugs.jqueryui.com/ticket/4437"&gt;http://bugs.jqueryui.com/ticket/4437&lt;/a&gt;. &lt;span style="color: orange;"&gt;width:auto&lt;/span&gt; is very important for most dialogs because you often don't know how large the dialog's content is (think e.g. about multi-language labels). General you will not get problems with &lt;span style="color: orange;"&gt;width:auto&lt;/span&gt; and can write&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;div id="dialog" title="My dialog"&amp;gt;&lt;br /&gt;  ... content ...&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;br /&gt;$('#dialog').dialog({&lt;br /&gt;    modal: true,&lt;br /&gt;    height: 'auto',&lt;br /&gt;    width: 'auto'&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;or define CSS class&lt;br /&gt;&lt;pre class="brush:css"&gt;.autoWidthDialog {&lt;br /&gt;    width: auto !important;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;and write in PrimeFaces&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;p:dialog id="dialog" styleClass="autoWidthDialog" header="My dialog"&amp;gt;&lt;br /&gt;  ... content ...&lt;br /&gt;&amp;lt;/p:dialog&amp;gt;&lt;br /&gt;&lt;/pre&gt;Working well except one problem - broken dialog's header in IE7 and below. Titelbar is shrunk to the title text length. Unfortunately, jQuery team doesn't want to fix this issue and support flexible dialogs with &lt;span style="color: orange;"&gt;width:auto&lt;/span&gt;, so that a workaround is needed. Annoying scrollbars on page for modal dialogs should be fixed too. I came up with the following solution:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Native jQuery UI dialog:&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush:js"&gt;jQuery("#dialog").dialog({&lt;br /&gt;    modal: true,&lt;br /&gt;    height: 'auto',&lt;br /&gt;    width: 'auto'&lt;br /&gt;    ... other various options ...&lt;br /&gt;}).bind("dialogopen", function(event, ui) {&lt;br /&gt;    // fix for width:auto in IE&lt;br /&gt;    var jqDialog = jQuery(this);&lt;br /&gt;    var parent = jqDialog.parent();&lt;br /&gt;    var contentWidth = jqDialog.width();&lt;br /&gt;    parent.find('.ui-dialog-titlebar').each(function() {&lt;br /&gt;        jQuery(this).width(contentWidth);&lt;br /&gt;    });&lt;br /&gt;    parent.width(contentWidth + 26);&lt;br /&gt;    jqDialog.dialog('option', 'position', 'center');&lt;br /&gt;&lt;br /&gt;    // fix for scrollbars in IE&lt;br /&gt;    jQuery('body').css('overflow', 'hidden');&lt;br /&gt;    jQuery('.ui-widget-overlay').css('width', '100%');&lt;br /&gt;}).bind("dialogclose", function(event, ui) {&lt;br /&gt;    // fix for width:auto in IE&lt;br /&gt;    jQuery(this).parent().css("width", "auto");&lt;br /&gt;&lt;br /&gt;    // fix for scrollbars in IE&lt;br /&gt;    jQuery('body').css('overflow', 'auto');&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;&lt;u&gt;PrimeFaces dialog built on the top of native one:&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;p:dialog id="dialog" styleClass="autoWidthDialog"&lt;br /&gt;          onShow="onShowAutoWidthDialog(this.jq);"&lt;br /&gt;          onHide="onHideAutoWidthDialog(this.jq);"&amp;gt;&lt;br /&gt;  ... content ...&lt;br /&gt;&amp;lt;/p:dialog&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre class="brush:js"&gt;function onShowAutoWidthDialog(jqDialog) {&lt;br /&gt;    // fix for auto width in IE&lt;br /&gt;    var parent = jqDialog.parent();&lt;br /&gt;    var contentWidth = jqDialog.width();&lt;br /&gt;    parent.find('.ui-dialog-titlebar').each(function() {&lt;br /&gt;        jQuery(this).width(contentWidth);&lt;br /&gt;&lt;br /&gt;    });&lt;br /&gt;    parent.removeClass(&amp;quot;autoWidthDialog&amp;quot;).width(contentWidth + 26);&lt;br /&gt;    jqDialog.dialog('option', 'position', 'center');&lt;br /&gt;&lt;br /&gt;    // fix for scrollbars in IE&lt;br /&gt;    jQuery('body').css('overflow', 'hidden');&lt;br /&gt;    jQuery('.ui-widget-overlay').css('width', '100%');&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function onHideAutoWidthDialog(jqDialog) {&lt;br /&gt;    // fix for auto width in IE&lt;br /&gt;    var parent = jqDialog.parent();&lt;br /&gt;    parent.find('.ui-dialog-titlebar').each(function() {&lt;br /&gt;        // reset titlebar width&lt;br /&gt;        jQuery(this).css('width', '');&lt;br /&gt;    });&lt;br /&gt;    parent.addClass(&amp;quot;autoWidthDialog&amp;quot;);&lt;br /&gt;&lt;br /&gt;    // fix for scrollbars in IE&lt;br /&gt;    jQuery('body').css('overflow', 'auto');&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;I use &lt;span style="color: orange;"&gt;onShow / onHide&lt;/span&gt; client side callbacks. Settings &lt;span style="color: orange;"&gt;onShow="onShowAutoWidthDialog(this.jq);"&lt;/span&gt; &lt;span style="color: orange;"&gt;onHide="onHideAutoWidthDialog(this.jq);"&lt;/span&gt; fix mentioned above IE issues. Unfortunately, PrimeFaces &lt;span style="color: orange;"&gt;p:confirmDialog&lt;/span&gt; doesn't have these attributes (why?), so that I had to add &lt;span style="color: orange;"&gt;onShow&lt;/span&gt; / &lt;span style="color: orange;"&gt;onHide&lt;/span&gt; to &lt;span style="color: orange;"&gt;p:confirmDialog&lt;/span&gt; similar to &lt;span style="color: orange;"&gt;p:dialog&lt;/span&gt;. Component / renderer classes can be easy extended and for JavaScript widget I can post the code if somebody needs it. :-)&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Edit:&lt;/u&gt; There isn't cross-browser pure CSS solution; I didn't find it and didn't see anywhere.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-5937159696596277406?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/5937159696596277406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/05/jquery-ui-dialog-with-auto-width-and.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/5937159696596277406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/5937159696596277406'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/05/jquery-ui-dialog-with-auto-width-and.html' title='Auto sized jQuery UI dialogs and PrimeFaces'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-7958730790535534980</id><published>2011-05-16T14:27:00.000-07:00</published><updated>2011-06-01T23:32:10.249-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JSON'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>JSON with GSON and abstract classes</title><content type='html'>I have switched to &lt;a href="http://code.google.com/p/google-gson/"&gt;Google Gson&lt;/a&gt; after many years of using &lt;a href="http://www.json.org/java/index.html"&gt;org.json library&lt;/a&gt; for supporting JSON data interchange format in Java. &lt;span style="color: orange;"&gt;org.json&lt;/span&gt; is a lower-level library, so that you have to create &lt;span style="color: orange;"&gt;JSONObject&lt;/span&gt;, &lt;span style="color: orange;"&gt;JSONArray&lt;/span&gt;, &lt;span style="color: orange;"&gt;JSONString&lt;/span&gt;, ... and do other low-level work. &lt;span style="color: orange;"&gt;Gson&lt;/span&gt; simplifies this work. It provides simple &lt;span style="color: orange;"&gt;toJson()&lt;/span&gt; and &lt;span style="color: orange;"&gt;fromJson()&lt;/span&gt; methods to convert arbitrary Java objects to JSON and vice-versa, supports Java Generics, allows custom representations for objects, generates compact and readability JSON output and has many other goodies. I love it more and more. The using is simple. Assume, we have a class called &lt;span style="color: orange;"&gt;Circle&lt;/span&gt;.&lt;br /&gt;&lt;pre class="brush:java"&gt;public class Circle {&lt;br /&gt;    private int radius = 10;&lt;br /&gt;    private String backgroundColor = "#FF0000";&lt;br /&gt;    private String borderColor = "#000000";&lt;br /&gt;    private double scaleFactor = 0.5;&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;    // getter / setter&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Serialization (Java object --&amp;gt; JSON) can be done as follows:&lt;br /&gt;&lt;pre class="brush:java"&gt;Circle circle = new Circle();&lt;br /&gt;Gson gson = new Gson();&lt;br /&gt;String json = gson.toJson(circle); &lt;br /&gt;==&amp;gt; json is&lt;br /&gt;{&lt;br /&gt;    "radius": 10,&lt;br /&gt;    "backgroundColor": "#FF0000",&lt;br /&gt;    "borderColor": "#000000",&lt;br /&gt;    "scaleFactor": 0.5,&lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Deserialization (JSON --&amp;gt; Java object) is just one line of code:&lt;br /&gt;&lt;pre class="brush:java"&gt;Circle circle2 = gson.fromJson(json, Circle.class);  &lt;br /&gt;==&amp;gt; circle2 is the same as the circle above&lt;br /&gt;&lt;/pre&gt;Everything works like a charm. There is only one problem I have faced with abstract classes. Assume, we have an abstract class &lt;span style="color: orange;"&gt;AbstractElement&lt;/span&gt; and many other classes extending this one&lt;br /&gt;&lt;pre class="brush:java"&gt;public abstract class AbstractElement {&lt;br /&gt;    private String uuid;&lt;br /&gt;&lt;br /&gt;    // getter / setter&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Circle extends AbstractElement {&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Rectangle extends AbstractElement {&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Ellipse extends AbstractElement {&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Assume now, we store all concrete classes in a list or a map parametrized with &lt;span style="color: orange;"&gt;AbstractElement&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;public class Whiteboard&lt;br /&gt;{&lt;br /&gt;    private Map&amp;lt;String, AbstractElement&amp;gt; elements = &lt;br /&gt;            new LinkedHashMap&amp;lt;String, AbstractElement&amp;gt;();&lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The problem is that the concrete class is undisclosed during deserialization. It's unknown in the JSON representation of Whiteboard. How the right Java class should be instantiated from the JSON representation and put into the &lt;span style="color: orange;"&gt;Map&amp;lt;String, AbstractElement&amp;gt; elements&lt;/span&gt;? I have nothing found in the documentation what would address this problem. It is obvious that we need to store a meta information in JSON representations about concrete classes. That's for sure. &lt;span style="color: orange;"&gt;Gson&lt;/span&gt; allows you to register your own custom serializers and deserializers. That's a power feature of &lt;span style="color: orange;"&gt;Gson&lt;/span&gt;. Sometimes default representation is not what you want. This is often the case e.g. when dealing with third-party library classes. There are enough examples of how to write custom serializers / deserializers. I'm going to create an adapter class implementing both interfaces &lt;span style="color: orange;"&gt;JsonSerializer&lt;/span&gt;, &lt;span style="color: orange;"&gt;JsonDeserializer&lt;/span&gt; and to register it for my abstract class &lt;span style="color: orange;"&gt;AbstractElement&lt;/span&gt;.&lt;br /&gt;&lt;pre class="brush:java"&gt;GsonBuilder gsonBilder = new GsonBuilder();&lt;br /&gt;gsonBilder.registerTypeAdapter(AbstractElement.class, new AbstractElementAdapter());&lt;br /&gt;Gson gson = gsonBilder.create();&lt;br /&gt;&lt;/pre&gt;And here is &lt;span style="color: orange;"&gt;AbstractElementAdapter&lt;/span&gt;:&lt;br /&gt;&lt;pre class="brush:java"&gt;package com.googlecode.whiteboard.json;&lt;br /&gt;&lt;br /&gt;import com.google.gson.*;&lt;br /&gt;import com.googlecode.whiteboard.model.base.AbstractElement;&lt;br /&gt;import java.lang.reflect.Type;&lt;br /&gt;&lt;br /&gt;public class AbstractElementAdapter implements JsonSerializer&amp;lt;AbstractElement&amp;gt;, JsonDeserializer&amp;lt;AbstractElement&amp;gt; {&lt;br /&gt;    @Override&lt;br /&gt;    public JsonElement serialize(AbstractElement src, Type typeOfSrc, JsonSerializationContext context) {&lt;br /&gt;        JsonObject result = new JsonObject();&lt;br /&gt;        result.add("type", new JsonPrimitive(src.getClass().getSimpleName()));&lt;br /&gt;        result.add("properties", context.serialize(src, src.getClass()));&lt;br /&gt;&lt;br /&gt;        return result;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public AbstractElement deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)&lt;br /&gt;        throws JsonParseException {&lt;br /&gt;        JsonObject jsonObject = json.getAsJsonObject();&lt;br /&gt;        String type = jsonObject.get("type").getAsString();&lt;br /&gt;        JsonElement element = jsonObject.get("properties");&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            return context.deserialize(element, Class.forName("com.googlecode.whiteboard.model." + type));&lt;br /&gt;        } catch (ClassNotFoundException cnfe) {&lt;br /&gt;            throw new JsonParseException("Unknown element type: " + type, cnfe);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;I add two JSON properties - one is "&lt;span style="color: orange;"&gt;type&lt;/span&gt;" and the other is "&lt;span style="color: orange;"&gt;properties&lt;/span&gt;". The first property holds a concrete implementation class (simple name) of the &lt;span style="color: orange;"&gt;AbstractElement&lt;/span&gt; and the second one holds the serialized object itself. The JSON looks like&lt;br /&gt;&lt;pre class="brush:java"&gt;{&lt;br /&gt;    "type": "Circle",&lt;br /&gt;    "properties": {&lt;br /&gt;        "radius": 10,&lt;br /&gt;        "backgroundColor": "#FF0000",&lt;br /&gt;        "borderColor": "#000000",&lt;br /&gt;        "scaleFactor": 0.5,&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;We benefit from the "&lt;span style="color: orange;"&gt;type&lt;/span&gt;" property during deserialization. The concrete class can be instantiated now by &lt;span style="color: orange;"&gt;Class.forName("com.googlecode.whiteboard.model." + type)&lt;/span&gt; where &lt;span style="color: orange;"&gt;"com.googlecode.whiteboard.model." + type&lt;/span&gt; is a fully qualified class name. The following call&lt;br /&gt;&lt;pre class="brush:java"&gt;&amp;nbsp;&lt;br /&gt;public &amp;lt;T&amp;gt; T deserialize(JsonElement json, Type typeOfT) throws JsonParseException&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;from &lt;span style="color: orange;"&gt;JsonDeserializationContext&lt;/span&gt; invokes default deserialization on the specified object and completes the job.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-7958730790535534980?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/7958730790535534980/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/05/json-with-gson-and-abstract-classes.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7958730790535534980'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7958730790535534980'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/05/json-with-gson-and-abstract-classes.html' title='JSON with GSON and abstract classes'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-3153072621330761414</id><published>2011-05-08T02:09:00.000-07:00</published><updated>2011-07-21T07:40:04.081-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='PrimeFaces'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='Ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title type='text'>Prevent multiple clicks in JSF</title><content type='html'>Preventation of multiple clicks on buttons / links is a common and important task during web development. There are many discussions about &lt;a href="http://web.archiveorange.com/archive/v/MgEiglS3nyMMnXLVN4ID"&gt;double click problem in JSF&lt;/a&gt; I will try to cover all relevant approaches.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1) Server-side solution.&lt;/b&gt;&lt;br /&gt;Server-side solutions are normally based on token concept, phase listeners, filters or other complex tricks. Here is just &lt;a href="http://www.jroller.com/mert/entry/jsf_preventing_double_form_submit"&gt;one example&lt;/a&gt; for the server-side preventation of double-form submit Server-side solutions have disadvantages. Every request is handled by a special phase listener, filter or something near it, even if we are not interesting in multiple clicks preventation. There are problems in a cluster environment if session data get replicated. This a real problem I faced many years ago - our server-side solution didn't work proper if the web application was running in a cluster environment. Client-side solutions seems to be simpler and are more reliable.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2) Disable button / link on click.&lt;/b&gt;&lt;br /&gt;The simplest client-side solution consists in writing &lt;span style="color: orange;"&gt;this.disabled=true&lt;/span&gt; in onclick. An example:&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;h:commandbutton action="..." onclick="this.disabled=true;" value="..."&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;I had kinda troubles with this solution and ajaxified buttons like PrimeFaces' &lt;span style="color: orange;"&gt;p:commandButton&lt;/span&gt; - it didn't work. Furthermore the entire button gets frozen and doesn't respond anymore. We want to have a still responding button or link if user clicks on it multiple times.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3) Ajax queue and request delaying.&lt;/b&gt;&lt;br /&gt;This is probably the best solution at all. Many popular component libraries already have this solution for the multiple clicks preventation. OpenFaces has e.g. a nice concept in order to avoid frequent requests. OpenFaces' Ajax framework sends only one request in case of several events during the short period of time specified with the "&lt;span style="color: orange;"&gt;delay&lt;/span&gt;" attribute. RichFaces has &lt;span style="color: orange;"&gt;a4j:queue&lt;/span&gt; and &lt;span style="color: orange;"&gt;a4j:attachQueue&lt;/span&gt;. These components have an attribute "&lt;span style="color: orange;"&gt;requestDelay&lt;/span&gt;". This attribute specifies the number of milliseconds to wait before sending a request in order to combine similar requests. The greater the value the fewer requests will be sent when fast typing. Similar requests in the queue are "combined" while waiting for the request delay. This feature results in just one request from a component being sent. For more details see &lt;a href="http://richfaces-showcase.appspot.com/richfaces/component-sample.jsf?demo=queue&amp;amp;skin=blueSky"&gt;RichFaces showcase&lt;/a&gt; and try to do double clicks to see they are "combined" to just one. Unfortunately, but PrimeFaces doesn't have similar feature what would prevent sending of miltiple requests from the same component like buttons / links, datatable filtering on keyup if user types very fast (important for large tables), etc.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4) Using jQuery's bind / unbind methods.&lt;/b&gt;&lt;br /&gt;Ajax queue prevents double clicks, but doesn't ensure sending of slow multiple clicks. I have implemented my own solution for PrimeFaces' buttons / links. The idea is to bind onlick handler &lt;span style="color: orange;"&gt;bind('click', function() {..})&lt;/span&gt; and call &lt;span style="color: orange;"&gt;unbind('click')&lt;/span&gt; within the handler :-) I have also tried &lt;a href="http://api.jquery.com/one/"&gt;jQuery .one()&lt;/a&gt; method but it didn't work as desired. We should prepare the renderer class at first. I have these lines there (only short outline for button renderer to get the idea):&lt;br /&gt;&lt;pre class="brush:java"&gt;writer.write(button.resolveWidgetVar() + &lt;br /&gt;    " = new PrimeFaces.widget.ExtendedCommandButton('" + clientId + "', {");&lt;br /&gt;...&lt;br /&gt;writer.write("});");&lt;br /&gt;if (button.isPreventMultiplyClicks()) {&lt;br /&gt;    writer.write(button.resolveWidgetVar() + ".bindOneClick('" + clientId + "', function(){" + onclick + "});");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: orange;"&gt;ExtendedCommandButton&lt;/span&gt; is an extended widget based on the PrimeFaces' one. &lt;span style="color: orange;"&gt;bindOneClick&lt;/span&gt; is a method in this widget and &lt;span style="color: orange;"&gt;onclick&lt;/span&gt; is an onlick handler generated by PrimeFaces for Ajax / non Ajax requests. The extension looks as follows:&lt;br /&gt;&lt;pre class="brush:js"&gt;PrimeFaces.widget.ExtendedCommandButton = function(id, cfg) {&lt;br /&gt;    PrimeFaces.widget.CommandButton(id, cfg);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;jQuery.extend(PrimeFaces.widget.ExtendedCommandButton.prototype, PrimeFaces.widget.CommandButton.prototype);&lt;br /&gt;&lt;br /&gt;PrimeFaces.widget.ExtendedCommandButton.prototype.bindOneClick = function(clientId, commandFunc) {&lt;br /&gt;    var buttonEl = jQuery(PrimeFaces.escapeClientId(clientId));&lt;br /&gt;    buttonEl.data('commandFunc', commandFunc);&lt;br /&gt;    buttonEl.unbind('click');&lt;br /&gt;&lt;br /&gt;    buttonEl.bind('click', function() {&lt;br /&gt;        buttonEl.unbind('click');&lt;br /&gt;        commandFunc();&lt;br /&gt;    });&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;One problem still exists - if user stays on the same page (in case of Ajax updates) and the button is not updated, it doesn't respond more by reason of unbind. We should "reinitialize" it. Therefore I added this method too:&lt;br /&gt;&lt;pre class="brush:js"&gt;PrimeFaces.widget.ExtendedCommandButton.prototype.reinitialize = function(clientId) {&lt;br /&gt;    var buttonEl = jQuery(PrimeFaces.escapeClientId(clientId));&lt;br /&gt;    buttonEl.unbind('click');&lt;br /&gt;&lt;br /&gt;    buttonEl.bind('click', function() {&lt;br /&gt;        buttonEl.unbind('click');&lt;br /&gt;        buttonEl.data('commandFunc')();&lt;br /&gt;    });&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;So, if we navigate to another page (a non-Ajax request), we can write now:&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;p:commandButton preventMultiplyClicks="true" ajax="false" ...&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;If user stays on the same page (an Ajax request), a call &lt;span style="color: orange;"&gt;PrimeFaces.widget.ExtendedCommandButton.reinitialize(clientId)&lt;/span&gt; is necessary in "&lt;span style="color: orange;"&gt;oncomplete&lt;/span&gt;" to get multi-click preventation working again. Like this&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;p:commandButton id="myButton" preventMultiplyClicks="true" ...&lt;br /&gt;                oncomplete="PrimeFaces.widget.ExtendedCommandLink.reinitialize('myButton')"&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;Or you can try to include the button Id to the "&lt;span style="color: orange;"&gt;update&lt;/span&gt;" attribute&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;p:commandButton preventMultiplyClicks="true" update="@this,..." ...&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: orange;"&gt;p:commandLink&lt;/span&gt; will be updated and reinitialized again. We can also extend the button renderer a little bit and reinitialize it automatically (if it's not in the Ajax update region). Result: the button / link will be a quite usually PrimeFaces' button / link with a new attribute for multiple clicks. No differences otherwise.&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;p:commandLink "general PF attributes" preventMultiplyClicks="true"&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-3153072621330761414?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/3153072621330761414/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/05/prevent-multiple-clicks-in-jsf.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/3153072621330761414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/3153072621330761414'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/05/prevent-multiple-clicks-in-jsf.html' title='Prevent multiple clicks in JSF'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-7042063359975365928</id><published>2011-05-02T07:34:00.000-07:00</published><updated>2011-05-03T00:23:42.411-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>What to do if @PostConstruct is not called for JSF managed beans?</title><content type='html'>I have read and faced self the problem that methods annotated with &lt;span style="color: orange;"&gt;@PostConstruct&lt;/span&gt; / &lt;span style="color: orange;"&gt;@PreDestroy&lt;/span&gt; get never called. Even in JEE 6 compliant servers (weird). This problem had e.g. Tomcat in early 6.x releases, Jetty 6.1.x, etc. Jetty 6.1.x maven plugin can not be used than during development.&lt;br /&gt;&lt;br /&gt;There is a simple solution when using Mojarra JSF. Well, if you use Spring framework, you probably don't have this problem. This post provides a solution for JSF projects without Spring (because it doesn't make sense to use Spring in small, lightweight projects). Since Mojarra 1.2 there is a context parameter for web.xml &lt;span style="color: orange;"&gt;com.sun.faces.injectionProvider&lt;/span&gt;. This parameter specifies a class that implements the &lt;span style="color: orange;"&gt;InjectionProvider SPI&lt;/span&gt;. This implementation represents a hook the JSF implementation will use to provide resource injection support. If no provider, shipped with application server, was found and &lt;span style="color: orange;"&gt;@PostConstruct&lt;/span&gt; / &lt;span style="color: orange;"&gt;@PreDestroy&lt;/span&gt; are not called, we can set the value for this context parameter to &lt;span style="color: orange;"&gt;com.sun.faces.vendor.WebContainerInjectionProvider&lt;/span&gt; as follows&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;context-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;com.sun.faces.injectionProvider&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;&lt;br /&gt;        com.sun.faces.vendor.WebContainerInjectionProvider&lt;br /&gt;    &amp;lt;/param-value&amp;gt;&lt;br /&gt;&amp;lt;/context-param&amp;gt;&lt;br /&gt;&lt;/pre&gt;Annotations will be parsed and annotated methods invoked now and you will see a message during application startup.&lt;br /&gt;&lt;pre class="brush:java"&gt;...&lt;br /&gt;02.05.2011 16:04:13 com.sun.faces.spi.InjectionProviderFactory createInstance&lt;br /&gt;INFO: JSF1048: PostConstruct/PreDestroy-Annotationen available. ...&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;It's also possible to use the JBoss implementaion &lt;span style="color: orange;"&gt;org.jboss.web.jsf.integration.injection.JBossInjectionProvider&lt;/span&gt;. I have never tested it, but I think it would be a proper alternative.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;context-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;com.sun.faces.injectionProvider&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;&lt;br /&gt;        org.jboss.web.jsf.integration.injection.JBossInjectionProvider&lt;br /&gt;    &amp;lt;/param-value&amp;gt;&lt;br /&gt;&amp;lt;/context-param&amp;gt;&lt;br /&gt;&lt;/pre&gt;JBoss 5 and above uses it automatically, so that no needs exist for the mentioned parameter.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-7042063359975365928?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/7042063359975365928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/05/what-to-do-if-postconstruct-not-called.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7042063359975365928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7042063359975365928'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/05/what-to-do-if-postconstruct-not-called.html' title='What to do if @PostConstruct is not called for JSF managed beans?'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-5900094452685867262</id><published>2011-04-30T03:54:00.000-07:00</published><updated>2011-05-01T01:35:26.406-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Get running Broadcom WLAN under OpenSuse 11.4</title><content type='html'>I &lt;a href="http://ovaraksin.blogspot.com/2010/09/wlan-with-dell-notebook-and-opensuse.html"&gt;described&lt;/a&gt; how I did it in OpenSuse 11.3. OpenSuse 11.4 is shipped with an open source driver &lt;span style="color: orange;"&gt;brcm80211&lt;/span&gt; on board and you don't need proprietary &lt;span style="color: orange;"&gt;broadcom-wl-...&lt;/span&gt; drivers anymore (downloaded by &lt;a href="http://packman.links2linux.de/"&gt;PackMan&lt;/a&gt;) for many new Broadcom cards. Please check &lt;a href="http://linuxwireless.org/en/users/Drivers/brcm80211"&gt;this page&lt;/a&gt; for compatibility issues before you start with an installation. To see details to the available Broadcom card, use the commando &lt;span style="color: orange;"&gt;lspci&lt;/span&gt;. My output is e.g.: &lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: white; color: purple;"&gt;&lt;b&gt;/sbin/lspci -nnk | grep -i -A2 broad&lt;/b&gt;&lt;/div&gt;&lt;div style="background-color: white; color: purple;"&gt;&lt;b&gt;12:00.0 Network controller [0280]: Broadcom Corporation BCM4313 802.11b/g/n Wireless LAN Controller [14e4:4727] (rev 01)&lt;/b&gt;&lt;/div&gt;&lt;div style="background-color: white; color: purple;"&gt;&lt;b&gt;Subsystem: Dell Device [1028:0010]&lt;/b&gt;&lt;/div&gt;&lt;div style="background-color: white; color: purple;"&gt;&lt;b&gt;13:00.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller [10ec:8168] (rev 03)&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;The driver &lt;span style="color: orange;"&gt;brcm80211&lt;/span&gt; supports BCM4313 and BCM43224, BCM43225, BCM4329 chips. The installation is straightforward.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1)&lt;/b&gt; Remove all WLAN configurations in NetworkManager.&lt;br /&gt;&lt;b&gt;2)&lt;/b&gt; Install kernel-firmware from a DVD with OpenSuse 11.4. That's is the file &lt;span style="color: orange;"&gt;kernel-firmware-2.6.38-1.2.1.noarch.rpm&lt;/span&gt;. You should see after that all &lt;span style="color: orange;"&gt;brcm80211&lt;/span&gt; stuff under &lt;span style="color: orange;"&gt;/lib/firmware/brcm&lt;/span&gt; &lt;br /&gt;&lt;b&gt;3)&lt;/b&gt; You will see &lt;span style="color: orange;"&gt;Broadcom WLAN Controller&lt;/span&gt; with the device name &lt;span style="color: orange;"&gt;wlan0&lt;/span&gt; in Yast's Network Settings. All stuff is recognized well. &lt;span style="color: orange;"&gt;Broadcom WLAN Controller&lt;/span&gt; needs a small configuration if you have a WLAN router (my one is FRITZ!Box Fon WLAN 7270). You should set default gateway and input WAP or WEP key for the authentication.&lt;br /&gt;&lt;b&gt;4)&lt;/b&gt; Reboot and enjoy the wireless LAN.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Edit:&lt;/b&gt; I&amp;nbsp; was asked whether b43 drivers (for old BCM chips) should be removed. Yes, you can remove b43 and broadcom-wl-... drivers or do them blacklisted (see blacklist  config files under /etc/modprobe.d/), so that they are not  loaded at all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-5900094452685867262?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/5900094452685867262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/04/get-running-broadcom-wlan-under.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/5900094452685867262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/5900094452685867262'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/04/get-running-broadcom-wlan-under.html' title='Get running Broadcom WLAN under OpenSuse 11.4'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-3301806218269577234</id><published>2011-04-13T13:42:00.000-07:00</published><updated>2011-07-21T07:42:54.661-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='PrimeFaces'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='Ajax'/><title type='text'>Hooking of PrimeFaces Ajax calls as a kind of callbacks. Part II.</title><content type='html'>This is the continuation of &lt;a href="http://ovaraksin.blogspot.com/2011/04/hooking-of-primefaces-ajax-calls-as.html"&gt;the part I&lt;/a&gt; where I intended to add client-side callbacks for any PrimeFaces Ajax calls. PrimeFaces components normally have callbacks like &lt;span style="color: orange;"&gt;onstart&lt;/span&gt; and &lt;span style="color: orange;"&gt;oncomplete&lt;/span&gt;, but not for all events. PrimeFaces tree has e.g. &lt;span style="color: orange;"&gt;onselectStart&lt;/span&gt; and &lt;span style="color: orange;"&gt;onselectComplete&lt;/span&gt;, but what is about &lt;span style="color: orange;"&gt;onexpandStart&lt;/span&gt; and &lt;span style="color: orange;"&gt;onexpandComplete&lt;/span&gt; in dynamic trees? I guess, all such callbacks would blow up the component interface. I believe all existing component libraries mimic each other and have countless callbacks and listeners as component attributes. Why do they need them at all for Ajax calls? There is &lt;span style="color: orange;"&gt;f:ajax&lt;/span&gt; and derivations like &lt;span style="color: orange;"&gt;p:ajax&lt;/span&gt; which already have "&lt;span style="color: orange;"&gt;listener&lt;/span&gt;", "&lt;span style="color: orange;"&gt;execute&lt;/span&gt;", "&lt;span style="color: orange;"&gt;render&lt;/span&gt;" attributes and provide all Ajax callbacks with "&lt;span style="color: orange;"&gt;onevent&lt;/span&gt;" attribute automatically. Do they really need to blow up component attributes or would be a simple attaching of Ajax behaviors enough? Well. It's not the topic of this post.&lt;br /&gt;&lt;br /&gt;The component &lt;span style="color: orange;"&gt;blockUI&lt;/span&gt; is used here as reference implementation. It prevents user activity with any part of the page as long as an Ajax request / response cycle is running. We need a component class &lt;span style="color: orange;"&gt;BlockUI.java&lt;/span&gt;, a renderer class &lt;span style="color: orange;"&gt;BlockUIRenderer.java&lt;/span&gt; and an JavaScript &lt;span style="color: orange;"&gt;blockUI.js&lt;/span&gt;. The component class is trivial. It has attributes "&lt;span style="color: orange;"&gt;widgetVar&lt;/span&gt;", "&lt;span style="color: orange;"&gt;for&lt;/span&gt;", "&lt;span style="color: orange;"&gt;forElement&lt;/span&gt;", "&lt;span style="color: orange;"&gt;source&lt;/span&gt;" und getter / setter. More interesting are the renderer and the script.&lt;br /&gt;&lt;br /&gt;&lt;div style="color: orange;"&gt;BlockUIRenderer.java&lt;/div&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;public class BlockUIRenderer extends CoreRenderer&lt;br /&gt;{&lt;br /&gt; private static final Log LOG = LogFactory.getLog(BlockUIRenderer.class);&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public void encodeEnd(FacesContext fc, UIComponent component) throws IOException {&lt;br /&gt;  encodeMarkup(fc, component);&lt;br /&gt;  encodeScript(fc, component);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void encodeMarkup(FacesContext fc, UIComponent component) throws IOException {&lt;br /&gt;  ResponseWriter writer = fc.getResponseWriter();&lt;br /&gt;&lt;br /&gt;  writer.startElement("div", null);&lt;br /&gt;  writer.writeAttribute("id", component.getClientId(fc) + "_content", null);&lt;br /&gt;  writer.writeAttribute("style", "display: none;", null);&lt;br /&gt;  renderChildren(fc, component);&lt;br /&gt;  writer.endElement("div");&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected void encodeScript(FacesContext fc, UIComponent component) throws IOException {&lt;br /&gt;  ResponseWriter writer = fc.getResponseWriter();&lt;br /&gt;  BlockUI blockUI = (BlockUI) component;&lt;br /&gt;  String clientId = blockUI.getClientId(fc);&lt;br /&gt;  String widgetVar = blockUI.resolveWidgetVar();&lt;br /&gt;&lt;br /&gt;  String source;&lt;br /&gt;  UIComponent sourceComponent = blockUI.findComponent(blockUI.getSource());&lt;br /&gt;  if (sourceComponent == null) {&lt;br /&gt;   source = "";&lt;br /&gt;   LOG.warn("Source component could not be found for 'source' = " + blockUI.getSource());&lt;br /&gt;  } else {&lt;br /&gt;   source = sourceComponent.getClientId(fc);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  String target;&lt;br /&gt;  if (blockUI.getFor() != null) {&lt;br /&gt;   UIComponent targetComponent = blockUI.findComponent(blockUI.getFor());&lt;br /&gt;   if (targetComponent == null) {&lt;br /&gt;    target = "";&lt;br /&gt;    LOG.warn("Target component could not be found for 'for' = " + blockUI.getFor());&lt;br /&gt;   } else {&lt;br /&gt;    target = targetComponent.getClientId(fc);&lt;br /&gt;   }&lt;br /&gt;  } else if (blockUI.getForElement() != null) {&lt;br /&gt;   target = blockUI.getForElement();&lt;br /&gt;  } else {&lt;br /&gt;   target = "";&lt;br /&gt;   LOG.warn("Target is missing, either 'for' or 'forElement' attribute is required");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  UIComponent facet = blockUI.getFacet("events");&lt;br /&gt;&lt;br /&gt;  // collect all f:param&lt;br /&gt;  List&amp;lt;UIParameter&amp;gt; uiParams = new ArrayList&amp;lt;UIParameter&amp;gt;();&lt;br /&gt;  if (facet instanceof UIParameter) {&lt;br /&gt;   // f:facet has one child and that's f:param&lt;br /&gt;   uiParams.add((UIParameter) facet);&lt;br /&gt;  } else if (facet != null &amp;amp;&amp;amp; facet.getChildren() != null) {&lt;br /&gt;   // f:facet has no or more than one child (all children included into an UIPanel)&lt;br /&gt;   for (UIComponent kid : facet.getChildren()) {&lt;br /&gt;    if (kid instanceof UIParameter) {&lt;br /&gt;     uiParams.add((UIParameter) kid);&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // build a regular expression for event key, value pair.&lt;br /&gt;  String eventRegExp;&lt;br /&gt;  if (uiParams.isEmpty()) {&lt;br /&gt;   // no or empty "events" facet means all events of the given source are accepted&lt;br /&gt;   eventRegExp = "/" + Constants.PARTIAL_SOURCE_PARAM + "=" + source + "(.)*$/";&lt;br /&gt;  } else {&lt;br /&gt;   StringBuffer sb = new StringBuffer("/");&lt;br /&gt;   sb.append(source);&lt;br /&gt;   sb.append("_");&lt;br /&gt;&lt;br /&gt;   Iterator&amp;lt;UIParameter&amp;gt; iter = uiParams.iterator();&lt;br /&gt;   while (iter.hasNext()) {&lt;br /&gt;    UIParameter param = iter.next();&lt;br /&gt;&lt;br /&gt;    // not set event name / value means any name / value is accepted&lt;br /&gt;    sb.append("(");&lt;br /&gt;    sb.append(param.getName() != null ? param.getName() : "(.)*");&lt;br /&gt;    sb.append("=");&lt;br /&gt;    sb.append(param.getValue() != null ? param.getValue() : "(.)*");&lt;br /&gt;    sb.append("$)");&lt;br /&gt;&lt;br /&gt;    if (iter.hasNext()) {&lt;br /&gt;     sb.append("|");&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   sb.append("/");&lt;br /&gt;   eventRegExp = sb.toString();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  writer.startElement("script", blockUI);&lt;br /&gt;  writer.writeAttribute("type", "text/javascript", null);&lt;br /&gt;  writer.write(widgetVar + " = new JsfToolkit.widget.BlockUI('"&lt;br /&gt;               + ComponentUtils.escapeJQueryId(clientId) + "','"&lt;br /&gt;               + ComponentUtils.escapeJQueryId(source) + "','"&lt;br /&gt;               + ComponentUtils.escapeJQueryId(target) + "'," + eventRegExp + ");");&lt;br /&gt;  writer.write(widgetVar + ".setupAjaxSend();");&lt;br /&gt;  writer.write(widgetVar + ".setupAjaxComplete();");&lt;br /&gt;&lt;br /&gt;  writer.endElement("script");&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public boolean getRendersChildren() {&lt;br /&gt;  return true;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public void encodeChildren(FacesContext fc, UIComponent component) throws IOException {&lt;br /&gt;  // nothing to do&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The most important thing is the building of regular expressions. If we are not interesting in any special events, we will only check whether the source component in available in passed Ajax parameters (see the JS script below). The regular expression using for this check is&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;/javax.faces.source=&amp;lt;source&amp;gt;(.)*$/&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;where &lt;span style="color: orange;"&gt;&amp;lt;source&amp;gt;&lt;/span&gt; is the clientId of the source component. Radio buttons and checkboxes I mentioned in &lt;a href="http://ovaraksin.blogspot.com/2011/04/hooking-of-primefaces-ajax-calls-as.html"&gt;the part I&lt;/a&gt; send e.g.&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;javax.faces.source=accessLevels_1&lt;br /&gt;javax.faces.source=accessLevels_2&lt;br /&gt;javax.faces.source=accessRights_1&lt;br /&gt;javax.faces.source=accessRights_2&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;The regular expressions should be therefore&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;/javax.faces.source=accessLevels(.)*$/&lt;br /&gt;/javax.faces.source=accessRights(.)*$/&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;If we interesting in specified events, we build a regular expression for each event and concatenate them with the logical OR-operator. A regular expression for each event looks as follows&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;/&amp;lt;source&amp;gt;_(&amp;lt;event name&amp;gt;=&amp;lt;event value&amp;gt;)$/&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;If the event name or value is not important, we use &lt;span style="color: orange;"&gt;(.)*&lt;/span&gt; for any strings (empty is also allowed). Some examples:&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;/dtPropTemplates_(filtering=true)$|dtPropTemplates_(sorting=true)$/&lt;br /&gt;/treeSocs_(action=SELECT)$/&lt;br /&gt;/selectedGroupsUsers_(instantSelectedRowIndex=(.)*)$/&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;Corresponding Ajax requests have parameters (Ajax options):&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;dtPropTemplates_filtering=true&lt;br /&gt;dtPropTemplates_sorting=true&lt;br /&gt;treeSocs_action=SELECT&lt;br /&gt;selectedGroupsUsers_instantSelectedRowIndex=&amp;lt;rowId&amp;gt;&lt;br /&gt;// &amp;lt;rowId&amp;gt; is the internal Id of the currently selected row&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="color: orange;"&gt;blockUI.js&lt;/div&gt;&lt;br /&gt;The script provides two functions to register &lt;span style="color: orange;"&gt;ajaxSend&lt;/span&gt; and &lt;span style="color: orange;"&gt;ajaxComplete&lt;/span&gt; events where I check Ajax options in order to find the appropriate event. The check uses mentioned above regular expressions.&lt;br /&gt;&lt;pre class="brush:js"&gt;JsfToolkit.widget.BlockUI = function(id, source, target, regExp) {&lt;br /&gt; var clientId = id;&lt;br /&gt; var sourceId = source;&lt;br /&gt; var targetId = target;&lt;br /&gt; var eventRegExp = regExp;&lt;br /&gt; &lt;br /&gt; // global settings&lt;br /&gt; jQuery.blockUI.defaults.theme = true;&lt;br /&gt; jQuery.blockUI.defaults.fadeIn = 0;&lt;br /&gt; jQuery.blockUI.defaults.fadeOut = 0;&lt;br /&gt; jQuery.blockUI.defaults.applyPlatformOpacityRules = false;&lt;br /&gt; &lt;br /&gt; /* public access */&lt;br /&gt; &lt;br /&gt; this.setupAjaxSend = function () {&lt;br /&gt;  jQuery(sourceId).ajaxSend(function(event, xhr, ajaxOptions) {&lt;br /&gt;   // first, check if event should be handled &lt;br /&gt;   if (isAppropriateEvent(ajaxOptions)) {&lt;br /&gt;    var targetEl = jQuery(targetId);&lt;br /&gt;&lt;br /&gt;    // second, check if the target element has been found&lt;br /&gt;    if (targetEl.length &amp;gt; 0) {&lt;br /&gt;     // block the target element&lt;br /&gt;     targetEl.block({message: jQuery(clientId + &amp;quot;_content&amp;quot;).html()});&lt;br /&gt;&lt;br /&gt;     // get the current counter&lt;br /&gt;     var blocksCount = targetEl.data(&amp;quot;blockUI.blocksCount&amp;quot;);&lt;br /&gt;     if (typeof blocksCount === 'undefined') {&lt;br /&gt;      blocksCount = 0;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     // increase the counter&lt;br /&gt;     targetEl.data(&amp;quot;blockUI.blocksCount&amp;quot;, blocksCount+1);&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  });&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; this.setupAjaxComplete = function () {&lt;br /&gt;  jQuery(sourceId).ajaxComplete(function(event, xhr, ajaxOptions) {&lt;br /&gt;   // first, check if event should be handled&lt;br /&gt;   if (isAppropriateEvent(ajaxOptions)) {&lt;br /&gt;    var targetEl = jQuery(targetId);&lt;br /&gt;&lt;br /&gt;    // second, check if the target element has been found&lt;br /&gt;    if (targetEl.length &amp;gt; 0) {&lt;br /&gt;     // get the current counter&lt;br /&gt;           var blocksCount = targetEl.data(&amp;quot;blockUI.blocksCount&amp;quot;);&lt;br /&gt;&lt;br /&gt;           // check the counter&lt;br /&gt;     if (typeof blocksCount !== 'undefined') {&lt;br /&gt;      if (blocksCount == 1) {&lt;br /&gt;       // unblock the target element and reset the counter&lt;br /&gt;       jQuery(targetId).unblock();&lt;br /&gt;       targetEl.data(&amp;quot;blockUI.blocksCount&amp;quot;, 0);&lt;br /&gt;      } else if (blocksCount &amp;gt; 1) {&lt;br /&gt;       // only decrease the counter&lt;br /&gt;       targetEl.data(&amp;quot;blockUI.blocksCount&amp;quot;, blocksCount-1);&lt;br /&gt;      }&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  });&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; /* private access */&lt;br /&gt; &lt;br /&gt; var isAppropriateEvent = function (ajaxOptions) {&lt;br /&gt;  if (typeof ajaxOptions === 'undefined' || ajaxOptions == null ||&lt;br /&gt;   typeof ajaxOptions.data === 'undefined' || ajaxOptions.data == null) {&lt;br /&gt;   return false;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // split options around ampersands&lt;br /&gt;  var params = ajaxOptions.data.split(/&amp;amp;/g);&lt;br /&gt;  &lt;br /&gt;  // loop over the ajax options and try to match events&lt;br /&gt;  for (var i = 0; i &amp;lt; params.length; i++) {&lt;br /&gt;   if (eventRegExp.test(params[i])) {&lt;br /&gt;    return true;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return false;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: orange;"&gt;ajaxSend&lt;/span&gt; increase a counter bound to target element and &lt;span style="color: orange;"&gt;ajaxComplete&lt;/span&gt; decrease the counter. This is necessary if many sources blocks the same target. The target is unblocked if the counter is 1. The parsing of Ajax options is the main part and the clou of the question how to find any Ajax events to be able to fire client-side callbacks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-3301806218269577234?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/3301806218269577234/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/04/hooking-of-primefaces-ajax-calls-as_13.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/3301806218269577234'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/3301806218269577234'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/04/hooking-of-primefaces-ajax-calls-as_13.html' title='Hooking of PrimeFaces Ajax calls as a kind of callbacks. Part II.'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-1242009190224230131</id><published>2011-04-09T10:10:00.000-07:00</published><updated>2011-07-21T07:43:23.659-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='PrimeFaces'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='Ajax'/><title type='text'>Hooking of PrimeFaces Ajax calls as a kind of callbacks. Part I.</title><content type='html'>Using PrimeFaces I have needed client-side callbacks for events causing Ajax calls like sorting, pagination, filtering of datatable or tree node expansion. I can understand that it's impossible to define all kinds of callbacks. Therefore I was looking for a generic way and believe I have found it. I'm able now to "add" any callbacks to any components. Firstly some words about PrimeFaces Ajax driven events. A PrimeFaces Ajax request triggered by any component has a parameter describing the event. It consist of component's clientId, underline, name and value, e.g. &lt;span style="color: orange;"&gt;myTabview_tabChange=true&lt;/span&gt;. We are especially interesting in names and values. They are e.g.&lt;br /&gt;&lt;pre class="brush:java"&gt;&amp;nbsp;&lt;br /&gt;Datatable:&lt;br /&gt;name="filtering" value="true"&lt;br /&gt;name="sorting" value="true"&lt;br /&gt;name="paging" value="true"&lt;br /&gt;&lt;br /&gt;Tree:&lt;br /&gt;name="action" value="SELECT"&lt;br /&gt;name="action" value="EXPAND"&lt;br /&gt;&lt;br /&gt;TabView:&lt;br /&gt;name="tabChange" value="true"&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;This anatomy is not disclosed. Name / value pairs are undocumented, so that you need to look into JS files (for something like &lt;span style="color: orange;"&gt;params[this.id + '_tabChange'] = true;&lt;/span&gt;) or corresponding component renderers to figure out what are the parameters of any event. The other problem is that a name / value pair can be changed in next releases. The new tree (since PrimeFaces 3.x) will have e.g.&lt;br /&gt;&lt;pre class="brush:java"&gt;&amp;nbsp;&lt;br /&gt;name="instantSelection" value="&amp;lt;Node Id&amp;gt;"&lt;br /&gt;name="expandNode" value="&amp;lt;Node Id&amp;gt;"&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;It would be very nice and appreciated by community if the PrimeFaces team could standardize and document all Ajax driven events. Please :-)&lt;br /&gt;&lt;br /&gt;jQuery has a capability to register callbacks for Ajax events. There are &lt;span style="color: orange;"&gt;ajaxStart&lt;/span&gt; .... &lt;span style="color: orange;"&gt;ajaxComplete&lt;/span&gt; events in jQuery. With &lt;span style="color: orange;"&gt;ajaxStart&lt;/span&gt; you can register a handler to be called when the first Ajax request begins, with &lt;span style="color: orange;"&gt;ajaxComplete&lt;/span&gt; a handler to be called when Ajax requests complete, etc. We can use them to catch PrimeFaces Ajax calls and check passed parameters in order to figure out whether the event occurs we are interesting in.&lt;br /&gt;&lt;br /&gt;I'm going to demonstrate this approach on basis of a component I have implemented recently. This component calls &lt;span style="color: orange;"&gt;blockUI&lt;/span&gt; and it's based on the &lt;a href="http://jquery.malsup.com/block/"&gt;jQuery plugin blockUI&lt;/a&gt;. By means of this component we can block any piece of page during various Ajax calls. Very handy if you have e.g. a large datatable and sorting, filtering, pagination takes much time. The component has the following parameters: "&lt;span style="color: orange;"&gt;widgetVar&lt;/span&gt;" for the underlying widget (as all PrimeFaces components have it), "&lt;span style="color: orange;"&gt;for&lt;/span&gt;", "&lt;span style="color: orange;"&gt;forElement&lt;/span&gt;" to specify target component or HTML element which gets blocked and "&lt;span style="color: orange;"&gt;source&lt;/span&gt;" to specify source component which causes an Ajax request. Events, we are interesting in, are specified via a facet "&lt;span style="color: orange;"&gt;events&lt;/span&gt;" and &lt;span style="color: orange;"&gt;f:param&lt;/span&gt; within the facet. I'm going to start with facelets part and show three examples.&lt;br /&gt;&lt;br /&gt;&lt;div style="color: orange;"&gt;Playing together with p:dataTable&lt;/div&gt;&lt;pre class="brush:xhtml"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;h:panelGroup id="dtPropTemplatesGroup" layout="block"&amp;gt;&lt;br /&gt; &amp;lt;p:dataTable id="dtPropTemplates" var="propTemplate"&lt;br /&gt;       value="#{propTemplates.templates}" paginator="true" rows="20" ...&amp;gt;&lt;br /&gt;  ...&lt;br /&gt; &amp;lt;/p:dataTable&amp;gt;&lt;br /&gt; &amp;lt;jtcomp:blockUI source="dtPropTemplates" for="dtPropTemplates"&amp;gt;&lt;br /&gt;  &amp;lt;f:facet name="events"&amp;gt;&lt;br /&gt;   &amp;lt;f:param name="filtering" value="true"/&amp;gt;&lt;br /&gt;   &amp;lt;f:param name="paging" value="true"/&amp;gt;&lt;br /&gt;   &amp;lt;f:param name="sorting" value="true"/&amp;gt;&lt;br /&gt;  &amp;lt;/f:facet&amp;gt;&lt;br /&gt;  &amp;lt;h:panelGrid columns="2"&amp;gt;&lt;br /&gt;   &amp;lt;h:graphicImage library="themes" name="app/images/ajaxIndicator.gif"/&amp;gt;&lt;br /&gt;   &amp;lt;h:outputText value="Please wait, data are processing ..."/&amp;gt;&lt;br /&gt;  &amp;lt;/h:panelGrid&amp;gt;&lt;br /&gt; &amp;lt;/jtcomp:blockUI&amp;gt;&lt;br /&gt;&amp;lt;/h:panelGroup&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;Filtering, paging and sorting events display a half transparent overlay over the same table and a rotating Ajax indicator with the message "Please wait, data are processing ...".&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-cDtb3h6ofEo/TaCO9IQfOfI/AAAAAAAAAEE/rel9vLfTvo8/s1600/blockTable.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="352" src="http://2.bp.blogspot.com/-cDtb3h6ofEo/TaCO9IQfOfI/AAAAAAAAAEE/rel9vLfTvo8/s640/blockTable.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="color: orange;"&gt;Playing together with p:tree&lt;/div&gt;&lt;pre class="brush:xhtml"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;h:panelGroup id="treeSocsGroup" layout="block"&amp;gt;&lt;br /&gt; &amp;lt;p:tree id="treeSocs" value="#{socsBean.socsRootNode}" var="socNode" &lt;br /&gt;  dynamic="true" cache="true" selectionMode="single" &lt;br /&gt;  nodeSelectListener="#{socsBean.onNodeSelect}"&lt;br /&gt;  nodeExpandListener="#{socsBean.onNodeExpand}" ...&amp;gt;&lt;br /&gt;  &amp;lt;p:treeNode&amp;gt;&lt;br /&gt;   &amp;lt;h:outputText value="#{socNode.displayName}" escape="false"/&amp;gt;&lt;br /&gt;  &amp;lt;/p:treeNode&amp;gt;&lt;br /&gt;  &amp;lt;p:treeNode type="leafSoc" styleClass="leafSoc"&amp;gt;&lt;br /&gt;   &amp;lt;h:outputText value="#{socNode.displayName}" styleClass="leafContent"/&amp;gt;&lt;br /&gt;  &amp;lt;/p:treeNode&amp;gt;&lt;br /&gt; &amp;lt;/p:tree&amp;gt;&lt;br /&gt; &amp;lt;jtcomp:blockUI source="treeSocs" forElement="overviewSocsRightGroup"&amp;gt;&lt;br /&gt;  &amp;lt;f:facet name="events"&amp;gt;&lt;br /&gt;   &amp;lt;f:param name="action" value="SELECT"/&amp;gt;&lt;br /&gt;  &amp;lt;/f:facet&amp;gt;&lt;br /&gt;  // the same stuff as above&lt;br /&gt; &amp;lt;/jtcomp:blockUI&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;h:panelGroup id="overviewSocsRightGroup" layout="block"&amp;gt;&lt;br /&gt;  // menus, tables and other stuff&lt;br /&gt; &amp;lt;/h:panelGroup&amp;gt;&lt;br /&gt;&amp;lt;/h:panelGroup&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;A click on any tree node blocks the &lt;span style="color: orange;"&gt;panelGroup&lt;/span&gt; with id "&lt;span style="color: orange;"&gt;overviewSocsRightGroup&lt;/span&gt;" and the mentioned above overlay, indicator and message are displayed.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-UmsKpTUKAvM/TaCPkHBMNBI/AAAAAAAAAEI/VZ9F7Oxcq78/s1600/blockTree.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="218" src="http://2.bp.blogspot.com/-UmsKpTUKAvM/TaCPkHBMNBI/AAAAAAAAAEI/VZ9F7Oxcq78/s640/blockTree.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="color: orange;"&gt;Playing together with p:ajax&lt;/div&gt;&lt;br /&gt;Sometimes we are not interesting in any special events. In this case no f:facet for events is required. Assume we have a table, radio buttons and checkboxes. A click on any table row should block the radio buttons and checkboxes. A click on any radio button or checkbox should block the table, radio buttons and checkboxes. Remaining part of the page should stay untouched. Note: tables should be wrapped with a div element if they have to be blocked because a table can't be blocked nice in all browsers.&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;h:panelGroup id="rightsGroup" layout="block"&amp;gt;&lt;br /&gt; &amp;lt;h:panelGroup id="selectedGroupsUsersGroup"&amp;gt;&lt;br /&gt;  &amp;lt;p:dataTable id="selectedGroupsUsers" var="selGrUs" value="#{rightsBean.selectedGroupsUsers}" dynamic="false"&lt;br /&gt;        selection="#{rightsBean.selectedGroupUser}" selectionMode="single" update="levelsRightsGrid"&amp;gt;&lt;br /&gt;   ...&lt;br /&gt;  &amp;lt;/p:dataTable&amp;gt;&lt;br /&gt;  &amp;lt;jtcomp:blockUI source="selectedGroupsUsers" forElement="levelsRightsPanel"&amp;gt;&lt;br /&gt;   &amp;lt;f:facet name="events"&amp;gt;&lt;br /&gt;    &amp;lt;f:param name="instantSelectedRowIndex"/&amp;gt;&lt;br /&gt;   &amp;lt;/f:facet&amp;gt;&lt;br /&gt;   // the same stuff as above&lt;br /&gt;  &amp;lt;/jtcomp:blockUI&amp;gt;&lt;br /&gt; &amp;lt;/h:panelGroup&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;h:panelGrid id="levelsRightsGrid" columns="2"&amp;gt;&lt;br /&gt;  &amp;lt;h:panelGroup id="accessLevelsGroup"&amp;gt;&lt;br /&gt;   &amp;lt;h:selectOneRadio id="accessLevels" value="#{rightsBean.level}" layout="pageDirection"&amp;gt;&lt;br /&gt;    &amp;lt;f:selectItem itemLabel="Custom" itemValue="Custom" itemDisabled="true"/&amp;gt;&lt;br /&gt;    &amp;lt;f:selectItems value="#{rightsBean.selectableLevels}"/&amp;gt;&lt;br /&gt;    &amp;lt;p:ajax event="click" process="@this" update="accessRightsGroup,selectedGroupsUsersGroup"/&amp;gt;&lt;br /&gt;   &amp;lt;/h:selectOneRadio&amp;gt;&lt;br /&gt;   &amp;lt;jtcomp:blockUI source="accessLevels" for="rightsGroup"&amp;gt;&lt;br /&gt;    // the same stuff as above&lt;br /&gt;   &amp;lt;/jtcomp:blockUI&amp;gt;&lt;br /&gt;  &amp;lt;/h:panelGroup&amp;gt;&lt;br /&gt;  &lt;br /&gt;  &amp;lt;h:panelGroup id="accessRightsGroup"&amp;gt;&lt;br /&gt;   &amp;lt;h:selectManyCheckbox id="accessRights" value="#{rightsBean.selectedAccessRights}" layout="pageDirection"&amp;gt;&lt;br /&gt;    &amp;lt;f:selectItems value="#{rightsBean.accessRights}"/&amp;gt;&lt;br /&gt;    &amp;lt;p:ajax event="click" process="@this" update="accessLevelsGroup,selectedGroupsUsersGroup"/&amp;gt;&lt;br /&gt;   &amp;lt;/h:selectManyCheckbox&amp;gt;&lt;br /&gt;   &amp;lt;jtcomp:blockUI source="accessRights" for="rightsGroup"&amp;gt;&lt;br /&gt;    // the same stuff as above&lt;br /&gt;   &amp;lt;/jtcomp:blockUI&amp;gt;&lt;br /&gt;  &amp;lt;/h:panelGroup&amp;gt;&lt;br /&gt; &amp;lt;/h:panelGrid&amp;gt;&lt;br /&gt;&amp;lt;/h:panelGroup&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-pbc7TUGaN7M/TaCQH_QUXyI/AAAAAAAAAEM/cDjxhjnyEIM/s1600/blockPanel.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="177" src="http://4.bp.blogspot.com/-pbc7TUGaN7M/TaCQH_QUXyI/AAAAAAAAAEM/cDjxhjnyEIM/s640/blockPanel.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-OY-nQ7gwhT0/TaCQc-kdrjI/AAAAAAAAAEQ/23zkSY7SkFg/s1600/blockPanelTable.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="184" src="http://1.bp.blogspot.com/-OY-nQ7gwhT0/TaCQc-kdrjI/AAAAAAAAAEQ/23zkSY7SkFg/s640/blockPanelTable.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The event &lt;span class="Apple-style-span" style="color: orange;"&gt;instantSelectedRowIndex&lt;/span&gt; doesn't have a specified value. That means we are not interesting in a value (everything is valid). Unfortunately Ajax handlers can not be bound with jQuery &lt;span style="color: orange;"&gt;.live()&lt;/span&gt; method. Therefore I had to wrap radio button and checkboxes with a &lt;span style="color: orange;"&gt;h:panelGroup&lt;/span&gt; to get &lt;span style="color: orange;"&gt;blockUI&lt;/span&gt; updated every time together with corresponding radio button and checkboxes.&lt;br /&gt;&lt;br /&gt;The second part will cover the implementation and reveal more details. Stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-1242009190224230131?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/1242009190224230131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/04/hooking-of-primefaces-ajax-calls-as.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1242009190224230131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1242009190224230131'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/04/hooking-of-primefaces-ajax-calls-as.html' title='Hooking of PrimeFaces Ajax calls as a kind of callbacks. Part I.'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-cDtb3h6ofEo/TaCO9IQfOfI/AAAAAAAAAEE/rel9vLfTvo8/s72-c/blockTable.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-8413134683166029588</id><published>2011-04-07T02:12:00.000-07:00</published><updated>2011-04-07T02:19:30.931-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='PrimeFaces'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>How to filter p:dataTable on enter event</title><content type='html'>PrimeFaces' datatable doesn't support the filtering for "&lt;span style="color: orange;"&gt;onenter&lt;/span&gt;" event. It's not a DOM event, but it makes sense for large datatables to filter a dataset when the enter (return) key was pressed. Many users complain that they can't filter large datasets on each keystroke, only hitting of return key makes sense for them. That's exactly my case too. I use "&lt;span style="color: orange;"&gt;onenter&lt;/span&gt;" event for filtering because a datatable sends too many requests if user inputs and removes characters very quickly. An update of the table is very slow then. The solution is not difficult. Use &lt;span style="color: orange;"&gt;filterEvent="enter"&lt;/span&gt; in any &lt;span style="color: orange;"&gt;p:column&lt;/span&gt; needing a filtering like this&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;p:dataTable id="myTable" var="user" value="#{myBean.users}"&lt;br /&gt;             widgetVar="myTblWidget"&amp;gt;&lt;br /&gt;  ...&lt;br /&gt;  &amp;lt;p:column filterBy="#{user.name}" filterEvent="enter"&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;  &amp;lt;/p:column&amp;gt;&lt;br /&gt;  ...&lt;br /&gt;&amp;lt;/p:dataTable&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;and place this little JavaScript direct after &lt;span style="color: orange;"&gt;p:dataTable&lt;/span&gt; (can be also placed into an ui:include for better reusing)&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;/* &amp;lt;![CDATA[ */&lt;br /&gt;  jQuery(myTblWidget.jqId).find('th .ui-column-filter[onenter]').each(function(idx) {&lt;br /&gt;  var curEl = jQuery(this);&lt;br /&gt;  curEl.unbind('keydown');&lt;br /&gt;&lt;br /&gt;  curEl.keydown(function(event) {&lt;br /&gt;    var e = (window.event) ? window.event : event;&lt;br /&gt;    if(e.keyCode == 13) {&lt;br /&gt;      event.preventDefault();&lt;br /&gt;      eval(curEl.attr('onenter'));&lt;br /&gt;    }&lt;br /&gt;  })&lt;br /&gt;});&lt;br /&gt;/* ]]&amp;gt; */&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;The script binds "&lt;span style="color: orange;"&gt;keydown&lt;/span&gt;" event for the enter key on every input field using for the filtering (select boxes using for this purpose don't matter here). If the enter key has been detected, the built-in client-side callback being executed (by means of the JS &lt;span style="color: orange;"&gt;eval&lt;/span&gt; function) and sends an Ajax request to filter the table. It works like a charm. I also have a meaningful tooltip for every input field using for the filtering. The reason is clear - this kind of the filtering is not always easy to understand for end users. A tooltip seems to be very handy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-8413134683166029588?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/8413134683166029588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/04/how-to-filter-pdatatable-on-enter-event.html#comment-form' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/8413134683166029588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/8413134683166029588'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/04/how-to-filter-pdatatable-on-enter-event.html' title='How to filter p:dataTable on enter event'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-316625325424648170</id><published>2011-04-01T01:44:00.000-07:00</published><updated>2011-04-01T01:55:18.536-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><title type='text'>Subclass creation and inheritance in JavaScript or how to extend widgets</title><content type='html'>There are many books and articles describing the inheritance in JavaScript. I'm using &lt;span style="color: orange;"&gt;Prototype&lt;/span&gt;, &lt;span style="color: orange;"&gt;jQuery &lt;/span&gt;an &lt;span style="color: orange;"&gt;YUI&lt;/span&gt; JavaScript frameworks in my old and new web projects. A quite common task for me is an extension of existing widgets. There is a &lt;a href="http://ejohn.org/blog/simple-javascript-inheritance/"&gt;classic article from John Resig&lt;/a&gt; which shows a pure simple solution for JavaScript inheritance without using of any frameworks. Nice implementation. I'm going to show my approved techniques with and without frameworks. They are quite simple. They work for me and I would like to share them with readers of my blog.&lt;br /&gt;&lt;br /&gt;Assume we have a JS object (widget) called &lt;span style="color: orange;"&gt;SuperWidget&lt;/span&gt; and want to create a subclass of it called &lt;span style="color: orange;"&gt;ExtendedWidget&lt;/span&gt;. Assume &lt;span style="color: orange;"&gt;ExtendedWidget&lt;/span&gt; has a constructor with four parameters and &lt;span style="color: orange;"&gt;SuperWidget&lt;/span&gt; with two parameters.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1) Pure JS&lt;/b&gt;&lt;br /&gt;First we create a new constructor for &lt;span style="color: orange;"&gt;ExtendedWidget&lt;/span&gt; and call the super constructor inside of this to make sure that the instance will be correctly initiated. After that we set some new property values. Finally if the constructor is created we set the prototype to a "&lt;span style="color: orange;"&gt;new SuperWidget&lt;/span&gt;".&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;function ExtendedWidget(param1, param2, param3, param4) {&lt;br /&gt;   // call super&lt;br /&gt;   this.SuperWidget = SuperWidget;&lt;br /&gt;   this.SuperWidget(param1, param2);&lt;br /&gt;   &lt;br /&gt;   // set additional properties&lt;br /&gt;   this.param3 = param3;&lt;br /&gt;   var param4 = param4;&lt;br /&gt;&lt;br /&gt;   // implement a new public method&lt;br /&gt;   this.myNewMethod = function(a, b) {&lt;br /&gt;      // do something&lt;br /&gt;      ...&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   // implement a new private method&lt;br /&gt;   var mySecondNewMethod = function(c, d) {&lt;br /&gt;      // do something&lt;br /&gt;      ...&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;ExtendedWidget.prototype = new SuperWidget;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;This examples also shows a definition of public and private fields and methods. The keyword "&lt;span style="color: orange;"&gt;this&lt;/span&gt;" marks fields and methods with public access and "&lt;span style="color: orange;"&gt;var&lt;/span&gt;" with private one. In this example "&lt;span style="color: orange;"&gt;param4&lt;/span&gt;" and "&lt;span style="color: orange;"&gt;mySecondNewMethod&lt;/span&gt;" can not be accessed outside after &lt;span style="color: orange;"&gt;ExtendedWidget&lt;/span&gt; was instantiated.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2) Yahoo UI&lt;/b&gt;&lt;br /&gt;Yahoo library offers a couple of simple calls out-of-box for subclass creation.&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;ExtendedWidget = function(param1, param2, param3, param4) {&lt;br /&gt;   // call super&lt;br /&gt;   ExtendedWidget.superclass.constructor.call(param1, param2);&lt;br /&gt;&lt;br /&gt;   // set additional properties&lt;br /&gt;   this.param3 = param3;&lt;br /&gt;   var param4 = param4;&lt;br /&gt;&lt;br /&gt;   // do something&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// extend super class&lt;br /&gt;YAHOO.lang.extend(ExtendedWidget, SuperWidget);&lt;br /&gt;&lt;br /&gt;// implement a new method&lt;br /&gt;ExtendedWidget.prototype.myNewMethod = function(a, b) {&lt;br /&gt;   // do something&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// extend an existing method for additional functionality&lt;br /&gt;ExtendedWidget.prototype.someMethod = function(c, d) {&lt;br /&gt;   ExtendedWidget.superclass.someMethod.call(this, c, d);&lt;br /&gt;   &lt;br /&gt;   // do something extra&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;3) jQuery&lt;/b&gt;&lt;br /&gt;jQuery doesn't offer this feature directly, but we can call the superclass constructor in the extended object and extend properties by using of "&lt;span style="color: orange;"&gt;extend&lt;/span&gt;" method. The method &lt;span style="color: orange;"&gt;jQuery.extend()&lt;/span&gt; merges the contents of two or more objects together. We need to merge prototypes.&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;ExtendedWidget = function(param1, param2, param3, param4) {&lt;br /&gt;   // call super    &lt;br /&gt;   SuperWidget(param1, param2);&lt;br /&gt;&lt;br /&gt;   // set additional properties&lt;br /&gt;   this.param3 = param3;&lt;br /&gt;   var param4 = param4;&lt;br /&gt;&lt;br /&gt;   // do something&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// merge properties into the first object ExtendedWidget&lt;br /&gt;jQuery.extend(ExtendedWidget.prototype, SuperWidget.prototype);&lt;br /&gt;&lt;br /&gt;// implement a new method&lt;br /&gt;ExtendedWidget.prototype.myNewMethod = function(a, b) {&lt;br /&gt;   // do something&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;4) Prototype&lt;/b&gt;&lt;br /&gt;Prototype offers the JS inheritance with "&lt;span style="color: orange;"&gt;Class.create&lt;/span&gt;". I don't want to blow up this post, read &lt;a href="http://www.prototypejs.org/api/class/create"&gt;the official documentation&lt;/a&gt; please :-)&lt;br /&gt;&lt;br /&gt;That's all. Now we can use &lt;span style="color: orange;"&gt;ExtendedWidget&lt;/span&gt; as the subclass of &lt;span style="color: orange;"&gt;SuperWidget&lt;/span&gt; like this&lt;br /&gt;&lt;pre class="brush:js"&gt;&amp;nbsp;&lt;br /&gt;var extendedWidget = new ExtendedWidget(1, 2, 3, 4);&lt;br /&gt;extendedWidget.myNewMethod("Hello", "World");&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;u&gt;Announcement&lt;/u&gt;: In the next post I will show how to extend a &lt;span style="color: orange;"&gt;PrimeFaces&lt;/span&gt; widget (my preferred JSF library) for command button in order to prevent multiple clicks. I will leverage the jQuery based approach 3). But before I want to present a quite special "delicacy" - hooking of PrimeFaces Ajax calls as a kind of callbacks. Anatomy of PrimeFaces events will be revealed. You will be able to "add" any callbacks to any components on-the-fly. As example I have implemented a new component based on the jQuery plugin &lt;span style="color: orange;"&gt;blockUI&lt;/span&gt; to block any piece of page during various Ajax calls.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-316625325424648170?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/316625325424648170/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/04/subclass-creation-and-inheritance-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/316625325424648170'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/316625325424648170'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/04/subclass-creation-and-inheritance-in.html' title='Subclass creation and inheritance in JavaScript or how to extend widgets'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-4721497236620300506</id><published>2011-03-20T02:22:00.000-07:00</published><updated>2011-05-05T03:53:34.714-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Install Java 1.6 and Tomcat 6 under Ubuntu</title><content type='html'>I have installed Java und Tomcat on my VPS &lt;a href="http://www.fractalsoft.net/"&gt;http://www.fractalsoft.net&lt;/a&gt; many times but never noted necessary steps. Here some helpful infos.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: orange;"&gt;1)&lt;/span&gt; Issue following command to find out current jdk version in apt-get&lt;br /&gt;apt-cache search jdk&lt;br /&gt;&lt;br /&gt;&lt;span style="color: orange;"&gt;2)&lt;/span&gt; Install java JRE with apt-get install&lt;br /&gt;sudo apt-get install openjdk-6-jre&lt;br /&gt;&lt;br /&gt;&lt;span style="color: orange;"&gt;3)&lt;/span&gt; Set environment variable JAVA_HOME. Copy following statement and append to /etc/profile or .bashrc&lt;br /&gt;export JAVA_HOME="/usr/lib/jvm/java-6-openjdk;"&lt;br /&gt;&lt;br /&gt;&lt;span style="color: orange;"&gt;4)&lt;/span&gt; Install Tomcat 6&lt;br /&gt;sudo apt-get install tomcat6 tomcat6-admin tomcat6-common tomcat6-user tomcat6-docs tomcat6-examples&lt;br /&gt;&lt;div style="color: orange;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="color: orange;"&gt;5)&lt;/span&gt; Change tomcat server to run on port 80 in&lt;br /&gt;/var/lib/tomcat6/conf/server.xml (symbolic link) or etc/tomcat6/server.xml&lt;br /&gt;&lt;br /&gt;&lt;span style="color: orange;"&gt;7)&lt;/span&gt; Start tomcat server sudo /etc/init.d/tomcat6 start&lt;br /&gt;Stop tomcat server sudo /etc/init.d/tomcat6 stop&lt;br /&gt;Restart tomcat server sudo /etc/init.d/tomcat6 restart&lt;br /&gt;Get tomcat server status sudo /etc/init.d/tomcat6 status&lt;br /&gt;&lt;br /&gt;&lt;span style="color: orange;"&gt;8)&lt;/span&gt; To enable admin web based features add the following lines to &lt;br /&gt;/etc/tomcat6/tomcat-user.xml&lt;br /&gt;&lt;br /&gt;&amp;lt;role rolename="manager"/&amp;gt;&lt;br /&gt;&amp;lt;role rolename="admin"/&amp;gt;&lt;br /&gt;&amp;lt;user name="admin" password="admin" roles="manager,admin"/&amp;gt;&lt;br /&gt;&lt;br /&gt;Manager app http://www.fractalsoft.net/manager/html has now user / pwd = “admin”.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: orange;"&gt;9)&lt;/span&gt; Adjust default Tomcat page below /var/lib/tomcat6/webapps/ROOT/index.html if nessesary.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Edit:&lt;/b&gt; If you get this exception&lt;br /&gt;&lt;div style="background-color: white; color: purple;"&gt;SEVERE: Exception sending context initialized event to listener instance of class com.sun.faces.config.ConfigureListener&lt;/div&gt;&lt;div style="background-color: white; color: purple;"&gt;java.lang.ExceptionInInitializerError&lt;/div&gt;&lt;div style="background-color: white; color: purple;"&gt;...&lt;/div&gt;&lt;div style="background-color: white; color: purple;"&gt;Caused by: java.security.AccessControlException: access denied (java.util.PropertyPermission com.sun.aas.installRoot read) at java.security.AccessControlContext.checkPermission(AccessControlContext.java:342)&lt;/div&gt;&lt;div style="background-color: white; color: purple;"&gt;...&lt;/div&gt;and the deployte web application doesn't start, set &lt;span style="color: orange;"&gt;TOMCAT6_SECURITY=no&lt;/span&gt; (instead of yes) in the file &lt;span style="color: orange;"&gt;/etc/init.d/tomcat6&lt;/span&gt;. Restart your Tomcat after that (login via &lt;span style="color: orange;"&gt;ssh username@hostname&lt;/span&gt; and call &lt;span style="color: orange;"&gt;sudo /etc/init.d/tomcat6 restart&lt;/span&gt;). Thanks to &lt;a href="http://www.icefaces.org/JForum/posts/list/15/15203.page#59836%20"&gt;this post from ICEFaces forum&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-4721497236620300506?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/4721497236620300506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/03/install-java-16-and-tomcat-6-under.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/4721497236620300506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/4721497236620300506'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/03/install-java-16-and-tomcat-6-under.html' title='Install Java 1.6 and Tomcat 6 under Ubuntu'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-6930887928384169566</id><published>2011-03-08T04:03:00.000-08:00</published><updated>2011-06-04T08:38:51.157-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='Validation'/><title type='text'>How to validate multiple required fields all at once</title><content type='html'>&lt;b&gt;Foreword:&lt;/b&gt;&lt;br /&gt;The most desired feature in JSF is a multi-component validation. At the moment there is a lack of support for this feature because there is no standard way to attach one validator to multiple fields. There are&lt;a href="http://seamframework.org/Documentation/JSF21"&gt; proposed enhancements to JSF 2.1&lt;/a&gt; which should cover this lack. These are "generic subtree validation" and "multi-component validation using bean validation". The aim of this article is to give an idea for multi-component validation. The main point is the validation of required fields in a real project.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Starting position:&lt;/b&gt;&lt;br /&gt;Many required fields with required="true" attribute. They produce default messages from JSF implementation like: &lt;span style="color: orange;"&gt;j_id_id19: Validation Error: Value is required&lt;/span&gt;. An end-user gets kinda confused.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Task definition:&lt;/b&gt;&lt;br /&gt;Improve the required validation message with less costs and without any touch of existing code if possible. We would like to have messages with exact labels belong to fields, like &lt;span style="color: orange;"&gt;"The required field 'User Name' is not filled in"&lt;/span&gt;. The message severity should be WARNING and not ERROR as produced with the JSF standard validator. The solution should be reliable, maintainable and have a good performance.&lt;br /&gt;&lt;br /&gt;We will go step by step, evaluate available solutions and figure out the best one.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1)&lt;/b&gt; The first Ad-hoc solution coming in mind is one with a custom validator for required fields I described in the &lt;a href="http://ovaraksin.blogspot.com/2011/02/custom-jsf-validator-for-required.html"&gt;previous post&lt;/a&gt;. Sure, it's not an ideal solution because we need to define the label text twice and to attach the validator to each field to be validated. It's not good maintainable as well, but there are cases (discussed below) where we need it.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2)&lt;/b&gt; BalusC wrote a useful post &lt;a href="http://balusc.blogspot.com/2007/12/validator-for-multiple-fields.html"&gt;"Validator for multiple fields"&lt;/a&gt;. His solution illustrates an idea how to attach a validator to the last component of the group (components are validated in the same order as defined) and gather Ids of the all component(s) to be validated. Nice, but hard-coded, not configurable and still needs many adjustments in the existing code.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3)&lt;/b&gt; Cagatay Civici presented in his blog a &lt;a href="http://cagataycivici.wordpress.com/2011/02/11/label-provider-for-jsf-input-components"&gt;nice approach&lt;/a&gt; based on &lt;span style="color: orange;"&gt;SystemEventListener&lt;/span&gt; and &lt;span style="color: orange;"&gt;PreValidateEvent&lt;/span&gt; for &lt;span style="color: orange;"&gt;HtmlOutputLabel&lt;/span&gt; components. Really interesting idea. But the first question coming in mind - why do we need to scan all labels and do the same work as it's already done by labels self? I mean, &lt;span style="color: orange;"&gt;LabelRenderer&lt;/span&gt; looks for the corresponding editable component in order to find out a proper client Id in the RENDER_RESPONSE phase. It seems, we are doing the same job twice. I'm developing document management systems and we sometimes have about 100 labels on a form. Document's or folder's properties have them in DMS. If we have 100 labels and only 1-2 required fields, we don't need to treat all 100 labels from the view point of performance. We need to treat 1-2 required fields and only when validation has failed (in best case is nothing to do at all). In my opinion, we should look for invalid fields at first and then for corresponding labels. Not inverted as in the proposed approach. Furthermore, there are some limitations. This solution doesn't consider the cross-implementations algorithm for &lt;a href="http://seamframework.org/Documentation/JSFEnhancementComponentReferencing"&gt;component referencing&lt;/a&gt;. Simple &lt;span style="color: orange;"&gt;findComponent&lt;/span&gt; is not enough. Mojarra walks up the ancestor chain and call &lt;span style="color: orange;"&gt;findComponent()&lt;/span&gt; for each component in the ancestor chain. If the root is reached, it walks down the successor chain. Obviously (if I got the picture), the value in "for" attribute and the Id of the corresponding editable component may not match in Mojarra. Result: If a label and its corresponding editable field are located in different forms for example, we are not always able to find the editable field starting from the label component. The last point is the fact that we can't use &lt;span style="color: orange;"&gt;h:outputLabel&lt;/span&gt; in certain circumstances and depend on &lt;span style="color: orange;"&gt;h:outputText&lt;/span&gt;. &lt;span style="color: orange;"&gt;h:outputText&lt;/span&gt; should be considered too. Message severity is not customizable, so that we need a custom validator.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4)&lt;/b&gt; Another great idea which gave me the right direction comes from the &lt;a href="http://www.mkyong.com/jsf2/multi-components-validator-in-jsf-2-0/"&gt;Mkyong blog&lt;/a&gt;. The idea is to group components, e.g. with a &lt;span style="color: orange;"&gt;h:panelGrid&lt;/span&gt; component, and attach the event tag &lt;span style="color: orange;"&gt;f:event&lt;/span&gt; with &lt;span style="color: orange;"&gt;PostValidateEvent&lt;/span&gt; to the group. &lt;span style="color: orange;"&gt;f:event&lt;/span&gt; expects "&lt;span style="color: orange;"&gt;listener&lt;/span&gt;" and "&lt;span style="color: orange;"&gt;type&lt;/span&gt;" attributes which have to be registered declarative. We are worried with this approach about the listener method for &lt;span style="color: orange;"&gt;PostValidateEvent&lt;/span&gt;, where we place it and how we write it, etc. It would be nice to hide this information and accomplish all work programmatically. The autor could probably achieve an optimization by extension of &lt;span style="color: orange;"&gt;h:panelGrid&lt;/span&gt; like&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;h:panelGrid columns="..." validateRequired="true"&amp;gt;&lt;br /&gt;&lt;/pre&gt;The component &lt;span style="color: orange;"&gt;HtmlPanelGrid&lt;/span&gt; would have &lt;span style="color: orange;"&gt;processEvent&lt;/span&gt; method.&lt;br /&gt;&lt;pre class="brush:java"&gt;@ListenerFor(systemEventClass = PostValidateEvent.class)&lt;br /&gt;public class HtmlPanelGrid extends javax.faces.component.html.HtmlPanelGrid&lt;br /&gt;{&lt;br /&gt;    protected enum PropertyKeys {&lt;br /&gt;        validateRequired;&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;    public void processEvent(ComponentSystemEvent event)&lt;br /&gt;                       throws AbortProcessingException {&lt;br /&gt;        if (isValidateRequired()) {&lt;br /&gt;            ....&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;I would like to avoid extensions of any components, but general I like the idea of component subtree validation by means of &lt;span style="color: orange;"&gt;PostValidateEvent&lt;/span&gt;. My idea is based on this system event and a custom &lt;span style="color: orange;"&gt;TagHandler&lt;/span&gt;. I want to write a tag handler with a zero configuration and apply it to the body tag&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;h:body&amp;gt;&lt;br /&gt;   &amp;lt;custom:requiredFieldsValidator/&amp;gt;&lt;br /&gt;   ...&lt;br /&gt;&amp;lt;/h:body&amp;gt;&lt;br /&gt;&lt;/pre&gt;or some other component acts as parent for required fields and their labels. Good candidates would be &lt;span style="color: orange;"&gt;h:panelGroup&lt;/span&gt;, &lt;span style="color: orange;"&gt;h:panelGrid&lt;/span&gt; or &lt;span style="color: orange;"&gt;h:dataTable&lt;/span&gt;. &lt;u&gt;Note:&lt;/u&gt; For Ajax requests &lt;span style="color: orange;"&gt;&amp;lt;custom:requiredFieldsValidator/&amp;gt;&lt;/span&gt; should be placed within area being processed. For cases where we can't use &lt;span style="color: orange;"&gt;h:outputLabel&lt;/span&gt; we would like to use &lt;span style="color: orange;"&gt;h:outputText&lt;/span&gt; with &lt;span style="color: orange;"&gt;&amp;lt;f:attribite name="for" value="..."/&amp;gt;&lt;/span&gt;. The custom validator for single editable fields (Ad-hoc solution mentioned above) should be applicable too because sometimes there is one label for two and more fields and other rare scenarios. It should also have the higher precedence than a multi-component validator. An example covering all cases:&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;h:panelGrid columns="2"&amp;gt;&lt;br /&gt;  &amp;lt;custom:requiredFieldsValidator/&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;h:outputLabel for="username" value="User name"/&amp;gt;&lt;br /&gt;  &amp;lt;h:inputText id="username" value="#{bean.username}" required="true"/&amp;gt;&lt;br /&gt;  &amp;lt;h:outputLabel for="password" value="Password"/&amp;gt;&lt;br /&gt;  &amp;lt;h:inputText id="password" value="#{bean.password}" required="true"/&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;h:outputText value="Confirm Password"&amp;gt;&lt;br /&gt;    &amp;lt;f:attribite name="for" value="confirmPassword"/&amp;gt;&lt;br /&gt;  &amp;lt;/h:outputText&amp;gt; &lt;br /&gt;  &amp;lt;h:inputText id="confirmPassword" &lt;br /&gt;               value="#{bean.confirmPassword}" required="true"/&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;h:outputText value="Start date - End date"&amp;gt;&lt;br /&gt;  &amp;lt;h:panelGroup&amp;gt;&lt;br /&gt;    &amp;lt;h:inputText value="#{bean.startDate}" required="true"&amp;gt;&lt;br /&gt;      &amp;lt;custom:requiredFieldValidator label="Start date"/&amp;gt;&lt;br /&gt;    &amp;lt;/h:inputText&amp;gt;&lt;br /&gt;    &amp;lt;h:inputText value="#{bean.endDate}" required="true"&amp;gt;&lt;br /&gt;      &amp;lt;custom:requiredFieldValidator label="End date"/&amp;gt;&lt;br /&gt;    &amp;lt;/h:inputText&amp;gt;&lt;br /&gt;  &amp;lt;/h:panelGroup&amp;gt;&lt;br /&gt;&amp;lt;/h:panelGrid&amp;gt;&lt;br /&gt;&lt;/pre&gt;The tag handler is straightforward. It calls &lt;span style="color: orange;"&gt;subscribeToEvent&lt;/span&gt; for &lt;span style="color: orange;"&gt;PostValidateEvent&lt;/span&gt; and its listener &lt;span style="color: orange;"&gt;ValidateRequiredFieldsEventListener&lt;/span&gt; (explained below).&lt;br /&gt;&lt;pre class="brush:java"&gt;import javax.faces.component.UIComponent;&lt;br /&gt;import javax.faces.event.PostValidateEvent;&lt;br /&gt;import javax.faces.event.SystemEvent;&lt;br /&gt;import javax.faces.view.facelets.FaceletContext;&lt;br /&gt;import javax.faces.view.facelets.TagConfig;&lt;br /&gt;import javax.faces.view.facelets.TagHandler;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;&lt;br /&gt;public class ValidateRequiredFieldsHandler extends TagHandler&lt;br /&gt;{&lt;br /&gt;    public ValidateRequiredFieldsHandler(TagConfig config) {&lt;br /&gt;        super(config);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void apply(FaceletContext fc, UIComponent parent) throws IOException {&lt;br /&gt;        if (isNew(parent)) {&lt;br /&gt;            Class&amp;lt;? extends SystemEvent&amp;gt; eventClass = PostValidateEvent.class;&lt;br /&gt;            parent.subscribeToEvent(eventClass, new ValidateRequiredFieldsEventListener());&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected static boolean isNew(UIComponent component) {&lt;br /&gt;        UIComponent c = component;&lt;br /&gt;        if (c != null) {&lt;br /&gt;            UIComponent parent = c.getParent();&lt;br /&gt;            if (parent != null) {&lt;br /&gt;                if (UIComponent.isCompositeComponent(parent)) {&lt;br /&gt;                    c = parent;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            return c.getParent() == null;&lt;br /&gt;        } else {&lt;br /&gt;            return false;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: orange;"&gt;ValidateRequiredFieldsHandler&lt;/span&gt; is registered in a tag library&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;tag&amp;gt;&lt;br /&gt;    &amp;lt;description&amp;gt;Handler for validation of required fields&amp;lt;/description&amp;gt;&lt;br /&gt;    &amp;lt;tag-name&amp;gt;requiredFieldsValidator&amp;lt;/tag-name&amp;gt;&lt;br /&gt;    &amp;lt;handler-class&amp;gt;&lt;br /&gt;        xyz.webapp.jsf.validator.ValidateRequiredFieldsHandler&lt;br /&gt;    &amp;lt;/handler-class&amp;gt;&lt;br /&gt;&amp;lt;/tag&amp;gt;&lt;br /&gt;&lt;/pre&gt;The message key for any empty required field is defined in the JSF 2 specification, &lt;span style="color: orange;"&gt;chapter 2.5.2.4 "Localized Application Messages"&lt;/span&gt;. We are going to redefine the message of this key in the own message bundle (registered in faces-config.xml) as follows&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;nbsp;&lt;br /&gt;javax.faces.component.UIInput.REQUIRED=xyz.faces.component.UIInput.REQUIRED&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;The event listener &lt;span style="color: orange;"&gt; ValidateRequiredFieldsEventListener&lt;/span&gt; iterates through all messages and looks for required fields which were empty. For each such field the corresponding label will be found and the message will be regenerated. The label will be present in the message which is more user friendly now.&lt;br /&gt;&lt;pre class="brush:java"&gt;import javax.faces.application.FacesMessage;&lt;br /&gt;import javax.faces.component.UIComponent;&lt;br /&gt;import javax.faces.context.FacesContext;&lt;br /&gt;import javax.faces.event.AbortProcessingException;&lt;br /&gt;import javax.faces.event.ComponentSystemEvent;&lt;br /&gt;import javax.faces.event.ComponentSystemEventListener;&lt;br /&gt;import java.io.Serializable;&lt;br /&gt;import java.util.Iterator;&lt;br /&gt;import java.util.ResourceBundle;&lt;br /&gt;&lt;br /&gt;public class ValidateRequiredFieldsEventListener implements ComponentSystemEventListener, Serializable&lt;br /&gt;{&lt;br /&gt;    private static final long serialVersionUID = 20110227L;&lt;br /&gt;&lt;br /&gt;    private static final String MESSAGE_SUMMARY_PLACEHOLDER =&lt;br /&gt;            "xyz.faces.component.UIInput.REQUIRED";&lt;br /&gt;&lt;br /&gt;    public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {&lt;br /&gt;        FacesContext fc = FacesContext.getCurrentInstance();&lt;br /&gt;        UIComponent parent = event.getComponent();&lt;br /&gt;        if (parent == null) {&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        Iterator&amp;lt;String&amp;gt; iterClientIds = fc.getClientIdsWithMessages();&lt;br /&gt;        while (iterClientIds.hasNext()) {&lt;br /&gt;            String clientId = iterClientIds.next();&lt;br /&gt;&lt;br /&gt;            Iterator&amp;lt;FacesMessage&amp;gt; iterFacesMessages = fc.getMessages(clientId);&lt;br /&gt;            while (iterFacesMessages.hasNext()) {&lt;br /&gt;                FacesMessage facesMessage = iterFacesMessages.next();&lt;br /&gt;&lt;br /&gt;                if (MESSAGE_SUMMARY_PLACEHOLDER.equals(facesMessage.getSummary())) {&lt;br /&gt;                    iterFacesMessages.remove();&lt;br /&gt;&lt;br /&gt;                    // find label&lt;br /&gt;                    ValidateRequiredFieldsCallback vrfCallback = &lt;br /&gt;                       new ValidateRequiredFieldsCallback(parent);&lt;br /&gt;                    parent.invokeOnComponent(fc, clientId, vrfCallback);&lt;br /&gt;&lt;br /&gt;                    String message;&lt;br /&gt;                    ResourceBundle resourceBundle = MessageUtils.getMessageBundle(fc);&lt;br /&gt;&lt;br /&gt;                    // create new user friendly message&lt;br /&gt;                    if (vrfCallback.getLabel() == null) {&lt;br /&gt;                        message = MessageUtils.getMessageText(&lt;br /&gt;                           resourceBundle, "validator.emptyMandatoryField.1");&lt;br /&gt;                    } else {&lt;br /&gt;                        message = MessageUtils.getMessageText(&lt;br /&gt;                           resourceBundle, "validator.emptyMandatoryField.2",&lt;br /&gt;                              vrfCallback.getLabel());&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                    fc.addMessage(clientId, new FacesMessage(FacesMessage.SEVERITY_WARN,&lt;br /&gt;                                  "", message));&lt;br /&gt;                    break;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: orange;"&gt;ValidateRequiredFieldsCallback&lt;/span&gt; is responsible for mentioned above cross-implementations algorithm for component referencing. I use &lt;span style="color: orange;"&gt;visitTree&lt;/span&gt; method for component traversing. &lt;span style="color: orange;"&gt;VisitLabelCallback&lt;/span&gt; encapsulates a check whether the corresponding label is encountered during the component traversing.&lt;br /&gt;&lt;pre class="brush:java"&gt;import javax.faces.component.ContextCallback;&lt;br /&gt;import javax.faces.component.UIComponent;&lt;br /&gt;import javax.faces.component.visit.VisitContext;&lt;br /&gt;import javax.faces.context.FacesContext;&lt;br /&gt;&lt;br /&gt;public class ValidateRequiredFieldsCallback implements ContextCallback&lt;br /&gt;{&lt;br /&gt;    private UIComponent parent;&lt;br /&gt;    private String label;&lt;br /&gt;&lt;br /&gt;    public ValidateRequiredFieldsCallback(UIComponent parent) {&lt;br /&gt;        this.parent = parent;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void invokeContextCallback(FacesContext fc, UIComponent component) {&lt;br /&gt;        UIComponent currentParent = parent;&lt;br /&gt;        VisitLabelCallback visitLabelCallback = new VisitLabelCallback(fc, component.getId());&lt;br /&gt;&lt;br /&gt;        while (currentParent != null) {&lt;br /&gt;            currentParent.visitTree(VisitContext.createVisitContext(fc), visitLabelCallback);&lt;br /&gt;&lt;br /&gt;            if (visitLabelCallback.getLabel() != null) {&lt;br /&gt;                label = visitLabelCallback.getLabel();&lt;br /&gt;                return;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            currentParent = currentParent.getParent();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        fc.getViewRoot().visitTree(VisitContext.createVisitContext(fc), visitLabelCallback);&lt;br /&gt;        label = visitLabelCallback.getLabel();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String getLabel() {&lt;br /&gt;        return label;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;u&gt;Note:&lt;/u&gt; Start point from invalid fields brings us a nice bonus. We could highlight invalid fields. e. g. with red borders. After a new message has been added (s. &lt;span style="color: orange;"&gt;ValidateRequiredFieldsEventListener&lt;/span&gt;), we could update the &lt;span style="color: orange;"&gt;styleClass&lt;/span&gt; attribute&lt;br /&gt;&lt;pre class="brush:java"&gt;String originalStyleClass = component.getAttributes().get("styleClass");&lt;br /&gt;component.getAttributes().put("styleClass", &lt;br /&gt;                          originalStyleClass + " invalidField");&lt;br /&gt;&lt;/pre&gt;CSS according to this&lt;br /&gt;&lt;pre class="brush:css"&gt;div.invalidField,&lt;br /&gt;select.invalidField,&lt;br /&gt;input.invalidField,&lt;br /&gt;.invalidField input {&lt;br /&gt;    border: solid 1px red;&lt;br /&gt;    line-height: 1.4em;&lt;br /&gt;    height: 1.4em;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;What does &lt;span style="color: orange;"&gt;VisitLabelCallback&lt;/span&gt; do exactly? It checks &lt;span style="color: orange;"&gt;HtmlOutputLabel&lt;/span&gt;, &lt;span style="color: orange;"&gt;UIOutput&lt;/span&gt; (like &lt;span style="color: orange;"&gt;h:outputText&lt;/span&gt;) and a custom composite component (not considered here &lt;span style="color: orange;"&gt;custom:requiredLabel&lt;/span&gt;). It uses a regular expression for values in „for“ attribute, so that valid definitions like&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;h:outputLabel for=":mainForm:myTable:userName" .../&amp;gt;&lt;br /&gt;&amp;lt;h:outputLabel for="mainForm:userName" .../&amp;gt;&lt;br /&gt;&amp;lt;h:outputLabel for=":userName" .../&amp;gt;&lt;br /&gt;&lt;/pre&gt;are considered.&lt;br /&gt;&lt;pre class="brush:java"&gt;import javax.faces.component.UIComponent;&lt;br /&gt;import javax.faces.component.UINamingContainer;&lt;br /&gt;import javax.faces.component.UIOutput;&lt;br /&gt;import javax.faces.component.html.HtmlOutputLabel;&lt;br /&gt;import javax.faces.component.visit.VisitCallback;&lt;br /&gt;import javax.faces.component.visit.VisitContext;&lt;br /&gt;import javax.faces.component.visit.VisitResult;&lt;br /&gt;import javax.faces.context.FacesContext;&lt;br /&gt;&lt;br /&gt;public class VisitLabelCallback implements VisitCallback&lt;br /&gt;{&lt;br /&gt;    private String regExprForAttr;&lt;br /&gt;    private String label;&lt;br /&gt;&lt;br /&gt;    public VisitLabelCallback(FacesContext context, String idOfInvalidComp) {&lt;br /&gt;        regExprForAttr = "(" + idOfInvalidComp + ")|.*[" + UINamingContainer.getSeparatorChar(context) + "]{1}(" + idOfInvalidComp + ")$";&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public VisitResult visit(VisitContext context, UIComponent target) {&lt;br /&gt;        if (target instanceof HtmlOutputLabel &amp;amp;&amp;amp; ((HtmlOutputLabel) target).getFor() != null) {&lt;br /&gt;            String forAttr = ((HtmlOutputLabel) target).getFor();&lt;br /&gt;            if (forAttr.matches(regExprForAttr)) {&lt;br /&gt;                label = (String) ((HtmlOutputLabel) target).getValue();&lt;br /&gt;&lt;br /&gt;                return VisitResult.COMPLETE;&lt;br /&gt;            }&lt;br /&gt;        } else if (target instanceof UIOutput &amp;amp;&amp;amp; target.getAttributes().get("for") != null) {&lt;br /&gt;            String forAttr = (String) target.getAttributes().get("for");&lt;br /&gt;            if (forAttr.matches(regExprForAttr)) {&lt;br /&gt;                label = (String) ((UIOutput) target).getValue();&lt;br /&gt;&lt;br /&gt;                return VisitResult.COMPLETE;&lt;br /&gt;            }&lt;br /&gt;        } else if (target != null &amp;amp;&amp;amp; UIComponent.isCompositeComponent(target) &amp;amp;&amp;amp; target.getAttributes().get("for") != null) {&lt;br /&gt;            // TODO: do more reliable check for requiredLabel.xhtml, e.g. check resource name&lt;br /&gt;            String forAttr = (String) target.getAttributes().get("for");&lt;br /&gt;            if (forAttr.matches(regExprForAttr)) {&lt;br /&gt;                label = (String) target.getAttributes().get("value");&lt;br /&gt;&lt;br /&gt;                return VisitResult.COMPLETE;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return VisitResult.ACCEPT;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String getLabel() {&lt;br /&gt;        return label;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Other validators are possible too by this way. The validator from BaluC's example can be rewritten by means of &lt;span style="color: orange;"&gt;PostValidateEvent&lt;/span&gt;, any "single" Date / Time / Number validators can be done multi-component capable, etc.&lt;br /&gt;&lt;br /&gt;The end of a long story. Your feedback is welcome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-6930887928384169566?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/6930887928384169566/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/03/how-to-validate-multiple-required.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/6930887928384169566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/6930887928384169566'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/03/how-to-validate-multiple-required.html' title='How to validate multiple required fields all at once'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-2265167688292267473</id><published>2011-03-01T02:42:00.000-08:00</published><updated>2011-03-01T02:44:34.280-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>JSF form for container-based authentication</title><content type='html'>If you have a HTML form with &lt;span style="color: orange;"&gt;j_security_check&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;form method="post" action="j_security_check"&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;and want to rewrite it as JSF &lt;span style="color: orange;"&gt;h:form&lt;/span&gt;, it's easy to do. You can write&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;h:form id="login" onsubmit="document.login.action = j_security_check;"&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;or better (if you aren't sure about client Id of the form)&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;h:form id="login" onsubmit="document.#{p:component('login')}.action='j_security_check';"&amp;gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: orange;"&gt;p:component&lt;/span&gt; is an EL function from the PrimeFaces library calculating client Id of any component. RichFaces has a similar function &lt;span style="color: orange;"&gt;rich:component&lt;/span&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-2265167688292267473?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/2265167688292267473/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/03/jsf-form-for-container-based.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2265167688292267473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2265167688292267473'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/03/jsf-form-for-container-based.html' title='JSF form for container-based authentication'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-1487961465596446060</id><published>2011-02-25T04:06:00.000-08:00</published><updated>2011-02-25T05:56:10.779-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>Custom JSF validator for required fields</title><content type='html'>JSF components implementing &lt;span style="color: orange;"&gt;EditableValueHolder &lt;/span&gt;interface have two attributes "&lt;span style="color: orange;"&gt;required&lt;/span&gt;" and "&lt;span style="color: orange;"&gt;requiredMessage&lt;/span&gt;" - a flag indicating that the user is required to input / select not empty value and a text for validation message. We can use that, but it's not flexible enough, we can't parameterize the message directly in view (facelets or jsp) and we have to do something for a proper message customization. What is about a custom validator attached to any required field? We will write one. At first we need to register such validator in a tag library.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;facelet-taglib version="2.0" ... &amp;gt;&lt;br /&gt;    &amp;lt;namespace&amp;gt;http://ip.client/ip-jsftoolkit/validator&amp;lt;/namespace&amp;gt;&lt;br /&gt;    &amp;lt;tag&amp;gt;&lt;br /&gt;        &amp;lt;tag-name&amp;gt;requiredFieldValidator&amp;lt;/tag-name&amp;gt;&lt;br /&gt;        &amp;lt;validator&amp;gt;&lt;br /&gt;            &amp;lt;validator-id&amp;gt;ip.client.jsftoolkit.RequiredFieldValidator&amp;lt;/validator-id&amp;gt;&lt;br /&gt;        &amp;lt;/validator&amp;gt;&lt;br /&gt;        &amp;lt;attribute&amp;gt;&lt;br /&gt;            &amp;lt;description&amp;gt;Resource bundle name for the required message&amp;lt;/description&amp;gt;&lt;br /&gt;            &amp;lt;name&amp;gt;bundle&amp;lt;/name&amp;gt;&lt;br /&gt;            &amp;lt;required&amp;gt;false&amp;lt;/required&amp;gt;&lt;br /&gt;            &amp;lt;type&amp;gt;java.lang.String&amp;lt;/type&amp;gt;&lt;br /&gt;        &amp;lt;/attribute&amp;gt;&lt;br /&gt;        &amp;lt;attribute&amp;gt;&lt;br /&gt;            &amp;lt;description&amp;gt;Key of the required message in the resource bundle&amp;lt;/description&amp;gt;&lt;br /&gt;            &amp;lt;name&amp;gt;key&amp;lt;/name&amp;gt;&lt;br /&gt;            &amp;lt;required&amp;gt;false&amp;lt;/required&amp;gt;&lt;br /&gt;            &amp;lt;type&amp;gt;java.lang.String&amp;lt;/type&amp;gt;&lt;br /&gt;        &amp;lt;/attribute&amp;gt;&lt;br /&gt;        &amp;lt;attribute&amp;gt;&lt;br /&gt;            &amp;lt;description&amp;gt;Label string for the required message&amp;lt;/description&amp;gt;&lt;br /&gt;            &amp;lt;name&amp;gt;label&amp;lt;/name&amp;gt;&lt;br /&gt;            &amp;lt;required&amp;gt;false&amp;lt;/required&amp;gt;&lt;br /&gt;            &amp;lt;type&amp;gt;java.lang.String&amp;lt;/type&amp;gt;&lt;br /&gt;        &amp;lt;/attribute&amp;gt;&lt;br /&gt;    &amp;lt;/tag&amp;gt;&lt;br /&gt;&amp;lt;/facelet-taglib&amp;gt;&lt;br /&gt;&lt;/pre&gt;We defined three attributes in order to achieve a high flexibility. A simple using would be&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;lt;h:outputLabel for="myInput" value="#{text['myinput']}"/&amp;gt;&lt;br /&gt;&amp;lt;h:inputText id="myInput" value="..."&amp;gt;&lt;br /&gt;    &amp;lt;jtv:requiredFieldValidator label="#{text['myinput']}"/&amp;gt;&lt;br /&gt;&amp;lt;/h:inputText&amp;gt;&lt;br /&gt;&lt;/pre&gt;The validator class itself is not difficult. Dependent on the "&lt;span style="color: orange;"&gt;key&lt;/span&gt;" parameter (key of the required message) and the "&lt;span style="color: orange;"&gt;label&lt;/span&gt;" parameter (text of the corresponding label) there are four cases how the message gets acquired.&lt;br /&gt;&lt;pre class="brush:java"&gt;/**&lt;br /&gt; * Validator for required fields.&lt;br /&gt; */&lt;br /&gt;@FacesValidator(value = RequiredFieldValidator.VALIDATOR_ID)&lt;br /&gt;public class RequiredFieldValidator implements Validator&lt;br /&gt;{&lt;br /&gt;    /** validator id */&lt;br /&gt;    public static final String VALIDATOR_ID = "ip.client.jsftoolkit.RequiredFieldValidator";&lt;br /&gt;&lt;br /&gt;    /** default bundle name */&lt;br /&gt;    public static final String DEFAULT_BUNDLE_NAME = "ip.client.jsftoolkit.validator.message";&lt;br /&gt;&lt;br /&gt;    private String bundle;&lt;br /&gt;    private String key;&lt;br /&gt;    private String label;&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public void validate(FacesContext facesContext,&lt;br /&gt;        UIComponent component, Object value) throws ValidatorException&lt;br /&gt;    {&lt;br /&gt;        if (!UIInput.isEmpty(value)) {&lt;br /&gt;           return;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        String message;&lt;br /&gt;        String bundleName;&lt;br /&gt;&lt;br /&gt;        if (bundle == null) {&lt;br /&gt;           bundleName = DEFAULT_BUNDLE_NAME;&lt;br /&gt;        } else {&lt;br /&gt;           bundleName = bundle;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        if (key == null &amp;amp;&amp;amp; label == null) {&lt;br /&gt;            message = MessageUtils.getMessageText(&lt;br /&gt;               MessageUtils.getResourceBundle(facesContext, bundleName),&lt;br /&gt;                  "jsftoolkit.validator.emptyMandatoryField.1");&lt;br /&gt;        } else if (key == null &amp;amp;&amp;amp; label != null) {&lt;br /&gt;            message = MessageUtils.getMessageText(&lt;br /&gt;               MessageUtils.getResourceBundle(facesContext, bundleName),&lt;br /&gt;                  "jsftoolkit.validator.emptyMandatoryField.2", label);&lt;br /&gt;        } else if (key != null &amp;amp;&amp;amp; label == null) {&lt;br /&gt;            message = MessageUtils.getMessageText(&lt;br /&gt;               MessageUtils.getResourceBundle(facesContext, bundleName), key);&lt;br /&gt;        } else {&lt;br /&gt;            message = MessageUtils.getMessageText(&lt;br /&gt;               MessageUtils.getResourceBundle(facesContext, bundleName), key, label);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_WARN, message, StringUtils.EMPTY));&lt;br /&gt;       &lt;br /&gt;        // getter / setter&lt;br /&gt;        ... &lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: orange;"&gt;MessageUtils &lt;/span&gt;is an utility class to get &lt;span style="color: orange;"&gt;ResourceBundle &lt;/span&gt;and message text. We also need two text in the resource bundle (property file)&lt;br /&gt;&lt;pre class="brush:xml"&gt;jsftoolkit.validator.emptyMandatoryField.1=Some required field is not filled in.&lt;br /&gt;jsftoolkit.validator.emptyMandatoryField.2=The required field '{0}' is not filled in.&lt;br /&gt;&lt;/pre&gt;and the following context parameter in &lt;span style="color: orange;"&gt;web.xml&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;context-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;javax.faces.VALIDATE_EMPTY_FIELDS&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;&lt;br /&gt;&amp;lt;/context-param&amp;gt;&lt;br /&gt;&lt;/pre&gt;This solution is not ideal because we need to define the label text (like &lt;span style="color: orange;"&gt;#{text['myinput']}&lt;/span&gt;) twice and to attach the validator to each field to be validated. A better and generic validator for multiple fields will be presented in the next post. Stay tuned!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-1487961465596446060?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/1487961465596446060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/02/custom-jsf-validator-for-required.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1487961465596446060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1487961465596446060'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/02/custom-jsf-validator-for-required.html' title='Custom JSF validator for required fields'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-7862160680567182926</id><published>2011-02-19T16:27:00.000-08:00</published><updated>2011-02-19T16:45:37.917-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>Invalidate browser cache with custom JSF resource handler</title><content type='html'>Browser caches static resources like CSS, JavaScript files, images if they don't have proper expire time in the response header. An usual task is to find a solution which allows refetching of resources with each software release. We can modify all resource URLs by appending "&lt;span style="color: orange;"&gt;&amp;amp;rv=1234&lt;/span&gt;" or "&lt;span style="color: orange;"&gt;?rv=1234&lt;/span&gt;" to the end. &lt;span style="color: orange;"&gt;rv&lt;/span&gt; is a current software revision. Such modified URL leads to the refetching of resources. The current revision can be acquired during project build and stored somewhere, e.g. in a text file, in order to make it available in the web application. Maven has e.g. a special plugin for this task called &lt;span style="color: orange;"&gt;buildnumber-maven-plugin&lt;/span&gt;. This plugin allows to get the current revision from a version control system.&lt;br /&gt;&lt;br /&gt;We will write a custom JSF resource handler &lt;span style="color: orange;"&gt;CustomResourceHandler&lt;/span&gt; which will accomplish the URL modifying. The resource handler can be registered in &lt;span style="color: orange;"&gt;faces-config.xml&lt;/span&gt; as follows:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;application&amp;gt;&lt;br /&gt;    &amp;lt;resource-handler&amp;gt;packagename.CustomResourceHandler&amp;lt;/resource-handler&amp;gt;&lt;br /&gt;&amp;lt;/application&amp;gt;&lt;br /&gt;&lt;/pre&gt;Writing of any resource handler is straightforward. We need to extend &lt;span style="color: orange;"&gt;javax.faces.application.ResourceHandlerWrapper&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;public class CustomResourceHandler extends javax.faces.application.ResourceHandlerWrapper&lt;br /&gt;{&lt;br /&gt;    private ResourceHandler wrapped;&lt;br /&gt;&lt;br /&gt;    public CustomResourceHandler(ResourceHandler wrapped) {&lt;br /&gt;        this.wrapped = wrapped;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public ResourceHandler getWrapped() {&lt;br /&gt;        return this.wrapped;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public Resource createResource(String resourceName, String libraryName) {&lt;br /&gt;        Resource resource = super.createResource(resourceName, libraryName);&lt;br /&gt;&lt;br /&gt;        // here a check of library name could be necessary, etc.&lt;br /&gt;        ...&lt;br /&gt;        return new CustomResource(resource);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;We need now a class &lt;span style="color: orange;"&gt;CustomResource&lt;/span&gt;. &lt;span style="color: orange;"&gt;CustomResource&lt;/span&gt; should extend &lt;span style="color: orange;"&gt;javax.faces.application.ResourceWrapper&lt;/span&gt; and delegate all calls to this wrapper class except one call &lt;span style="color: orange;"&gt;getRequestPath()&lt;/span&gt;. Method &lt;span style="color: orange;"&gt;getRequestPath()&lt;/span&gt; needs to be overwritten.&lt;br /&gt;&lt;pre class="brush:java"&gt;public class CustomResource extends javax.faces.application.ResourceWrapper&lt;br /&gt;{&lt;br /&gt;    private javax.faces.application.Resource resource;&lt;br /&gt;&lt;br /&gt;    public CustomResource(Resource resource) {&lt;br /&gt;        this.resource = resource;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public Resource getWrapped() {&lt;br /&gt;        return this.resource;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public String getRequestPath() {&lt;br /&gt;        String requestPath = resource.getRequestPath();&lt;br /&gt;                 &lt;br /&gt;        // get current revision&lt;br /&gt;        String revision = ...&lt;br /&gt;&lt;br /&gt;        if(requestPath.contains("?"))&lt;br /&gt;            requestPath = requestPath + "&amp;amp;rv=" + revision;&lt;br /&gt;        else&lt;br /&gt;            requestPath = requestPath + "?rv=" + revision;&lt;br /&gt;&lt;br /&gt;        return requestPath;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public String getContentType() {&lt;br /&gt;        return getWrapped().getContentType();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;That's all. For more control in Mojarra JSF implementation there are two handy config parameters for &lt;span style="color: orange;"&gt;web.xml&lt;/span&gt;.&lt;br /&gt;&lt;div style="color: orange;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;u&gt;&lt;span style="color: orange;"&gt;com.sun.faces.defaultResourceMaxAge&lt;/span&gt;&lt;/u&gt; set expire time (in milliseconds) into response header and is responsible for browser-caching. Default value in Production ProjectStage is ca. 10 min.&lt;br /&gt;&lt;u&gt;&lt;span style="color: orange;"&gt;com.sun.faces. resourceUpdateCheckPeriod&lt;/span&gt;&lt;/u&gt; gives frequency in minutes to check for changes to webapp artifacts that contain resources.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-7862160680567182926?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/7862160680567182926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/02/invalidate-browser-cache-with-custom.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7862160680567182926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7862160680567182926'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/02/invalidate-browser-cache-with-custom.html' title='Invalidate browser cache with custom JSF resource handler'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-1392473647846045958</id><published>2011-02-17T02:04:00.000-08:00</published><updated>2011-02-17T02:04:56.797-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><title type='text'>Two handy CSS hacks for Internet Explorer</title><content type='html'>Web developers often face with deficiencies of Internet Explorer. There are many CSS hacks for IE allowing to overcome deficiencies in most cases, but I always use two hacks which are valid for all IE versions. That are &lt;span style="color: orange;"&gt;* html&lt;/span&gt; and &lt;span style="color: orange;"&gt;\9&lt;/span&gt;. Examples:&lt;br /&gt;&lt;pre class="brush:css"&gt;&amp;nbsp;&lt;br /&gt;* html .ui-spinner {&lt;br /&gt;    vertical-align: middle;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.ui-spinner {&lt;br /&gt;    vertical-align: middle\9;&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;Only IE understand them. Other browsers ignore these syntax.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-1392473647846045958?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/1392473647846045958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/02/two-handy-css-hacks-for-internet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1392473647846045958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1392473647846045958'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/02/two-handy-css-hacks-for-internet.html' title='Two handy CSS hacks for Internet Explorer'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-7002306109919807258</id><published>2011-02-17T01:36:00.000-08:00</published><updated>2011-11-23T06:14:52.582-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='Facelets'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>Passing JSF action methods into ui:include</title><content type='html'>Parameters like Java plain, complex objects and beans can be transfered into an &lt;span style="color: orange;"&gt;ui:include&lt;/span&gt; to be available in the included page. An example:&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;ui:include src="/sections/edit.xhtml"&amp;gt;&lt;br /&gt;    &amp;lt;ui:param name="editBean" value="#{editTemplate}"/&amp;gt;&lt;br /&gt;    &amp;lt;ui:param name="param1" value="value1"/&amp;gt;&lt;br /&gt;    &amp;lt;ui:param name="param1" value="value1"/&amp;gt;&lt;br /&gt;&amp;lt;/ui:include&amp;gt;&lt;br /&gt;&lt;/pre&gt;The facelets &lt;span style="color: orange;"&gt;edit.xhtml&lt;/span&gt; has then an access to these parameters. Well, but what is about action methods? They can be passed by array notation. We can include a facelets from many other facelets and specify the action by its name. E.g.&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;lt;ui:include src="/sections/edit.xhtml"&amp;gt;&lt;br /&gt;    &amp;lt;ui:param name="editBean" value="#{editTemplate}"/&amp;gt;&lt;br /&gt;    &amp;lt;ui:param name="deleteAction" value="deleteById"/&amp;gt;&lt;br /&gt;    &amp;lt;ui:param name="obj" value="#{listTemplates.selectedId}"/&amp;gt;&lt;br /&gt;&amp;lt;/ui:include&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;ui:include src="/sections/edit.xhtml"&amp;gt;&lt;br /&gt;    &amp;lt;ui:param name="editBean" value="#{editTemplate}"/&amp;gt;&lt;br /&gt;    &amp;lt;ui:param name="deleteAction" value="deleteByTemplate"/&amp;gt;&lt;br /&gt;    &amp;lt;ui:param name="obj" value="#{listTemplates.selectedTemplate}"/&amp;gt;&lt;br /&gt;&amp;lt;/ui:include&amp;gt;&lt;br /&gt;&lt;/pre&gt;deleteAction is an action name as String which is defined in the passed bean &lt;span style="color: orange;"&gt;#{editTemplate}&lt;/span&gt;. In the included &lt;span style="color: orange;"&gt;edit.xhtml&lt;/span&gt; we can access the proper action and call it with parameter as follows&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;h:commandButton value="Delete" action="#{editBean['deleteAction'](obj)}"/&amp;gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;or if you don't use EL 2.x&lt;br /&gt;&lt;pre class="brush:xhtml"&gt;&amp;nbsp;&lt;br /&gt;&amp;lt;h:commandButton value="Delete" action="#{editBean['deleteAction']}"&amp;gt;&lt;br /&gt;    &amp;lt;f:setPropertyActionListener target="#{editBean.selectedObject}" value="#{obj}"/&amp;gt;&lt;br /&gt;&amp;lt;/h:commandButton&amp;gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;Like JavaScript objects we can use the array notation in EL expressions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-7002306109919807258?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/7002306109919807258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/02/passing-jsf-action-methods-into.html#comment-form' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7002306109919807258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7002306109919807258'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/02/passing-jsf-action-methods-into.html' title='Passing JSF action methods into ui:include'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-6762077533386347111</id><published>2011-02-09T06:16:00.000-08:00</published><updated>2011-02-24T23:21:36.836-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>Escape characters in ResponseWriter</title><content type='html'>While development of JSF components I have faced a task to escape apostrophe &lt;b&gt;'&lt;/b&gt; in the HTTP response generated by &lt;span style="color: orange;"&gt;javax.faces.context.ResponseWriter&lt;/span&gt;. Here is a solution:&lt;br /&gt;&lt;pre class="brush:java"&gt;ResponseWriter writer = facesContext.getResponseWriter();&lt;br /&gt;...&lt;br /&gt;// swap writers&lt;br /&gt;FastStringWriter fsw = new FastStringWriter();&lt;br /&gt;ResponseWriter clonedWriter = writer.cloneWithWriter(fsw);&lt;br /&gt;facesContext.setResponseWriter(clonedWriter);&lt;br /&gt;&lt;br /&gt;// render children&lt;br /&gt;renderChildren(facesContext, uiTreeNode);&lt;br /&gt;&lt;br /&gt;// restore the original writer&lt;br /&gt;facesContext.setResponseWriter(writer);&lt;br /&gt;&lt;br /&gt;// escape output and write it back&lt;br /&gt;String renderedKids = fsw.toString();&lt;br /&gt;if (renderedKids != null &amp;amp;&amp;amp; !renderedKids.isEmpty()) {&lt;br /&gt;    writer.write(renderedKids.replace("'", "\\\'"));&lt;br /&gt;}&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;We replace the original Writer by &lt;span style="color: orange;"&gt;FastStringWriter&lt;/span&gt;, write there, get the output from it, do escaping and write the escaped output to the response.&lt;br /&gt;&lt;br /&gt;P.S. This post was triggered by an &lt;a href="http://code.google.com/p/primefaces/issues/detail?id=981"&gt;issue&lt;/a&gt; in PrimeFaces. I guess, &lt;a href="http://download.oracle.com/javaee/5/api/javax/faces/context/ResponseWriter.html#writeText%28java.lang.Object,%20java.lang.String%29"&gt;writeText&lt;/a&gt; would do the escaping. But if you have a third-party library and don't have many control over the rendering of component subtrees (s. renderChildren), you have not much alternatives.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-6762077533386347111?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/6762077533386347111/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2011/02/escape-characters-in-responsewriter.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/6762077533386347111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/6762077533386347111'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2011/02/escape-characters-in-responsewriter.html' title='Escape characters in ResponseWriter'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-5831829871157348336</id><published>2010-12-20T02:26:00.000-08:00</published><updated>2010-12-20T02:31:38.933-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Subversion'/><title type='text'>Subversion - merge changes in trunk and brunch from command line</title><content type='html'>Command line junkies can merge revisions from branch to trunk via svn command if they have a SVN command line client:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Go to the project in the branch and show the log (via repo-browser or IDE).&lt;/li&gt;&lt;li&gt;Look the revision at the beginning of your changes. Subtract 1 from the revision number.&lt;/li&gt;&lt;li&gt;Look the revision at the end of your changes. Add 1 to the revision number.&lt;/li&gt;&lt;li&gt;Go to the trunk working copy and type "svn merge -r &amp;lt;revision from step 2&amp;gt;:&amp;lt;revision from step 3&amp;gt; branchURL".&lt;/li&gt;&lt;/ol&gt;&lt;u&gt;Example:&lt;/u&gt;&lt;br /&gt;&lt;div style="color: #fff2cc;"&gt;/svn/trunk/myproject&amp;gt; svn merge -r 30308:30648 svn+ssh://xyz.com:65000/var/svn/mycompany/dev/branches/1.0/myproject&lt;/div&gt;&lt;br /&gt;Conflicts (if they exist) must be resolved manually.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Another tip to file comparision between two projects (brunch vs. trunk).&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;Goto the the trunk working copy and type&lt;br /&gt;&lt;div style="color: #fff2cc;"&gt;svn -c &amp;lt;change&amp;gt; svn+ssh://xyz.com:65000/var/svn/mycompany/dev/branches/1.0/myproject&lt;/div&gt;&lt;br /&gt;This is a short command of&lt;br /&gt;&lt;div style="color: #fff2cc;"&gt;svn -r &amp;lt;change - 1&amp;gt;:&amp;lt;change&amp;gt; svn+ssh://xyz.com:65000/var/svn/mycompany/dev/branches/1.0/myproject&lt;/div&gt;&amp;lt;change&amp;gt; is the revision number in the branch to be compared with the head revision in the trunk.&lt;br /&gt;&lt;br /&gt;A bunch of changes can be compared with&lt;br /&gt;&lt;span style="color: #fff2cc;"&gt;svn -r &amp;lt;changeVon&amp;gt;:&amp;lt;changeBis&amp;gt; svn+ssh://xyz.com:65000/var/svn/mycompany/dev/branches/1.0/myproject&lt;/span&gt;&lt;br /&gt;where &amp;lt;changeVon&amp;gt; is the start revision and &amp;lt;changeBis&amp;gt; is the end one.&lt;br /&gt;&lt;br /&gt;The same operations can be done vice versa if you go to the brunch working copy and compare with trunk (by typing trunk URL).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-5831829871157348336?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/5831829871157348336/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/12/subversion-merge-changes-in-trunk-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/5831829871157348336'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/5831829871157348336'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/12/subversion-merge-changes-in-trunk-and.html' title='Subversion - merge changes in trunk and brunch from command line'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-7214762088517351087</id><published>2010-11-06T15:43:00.000-07:00</published><updated>2010-11-06T15:47:23.094-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Java-Plugin'/><title type='text'>Install SUN Java-Plugin für Firefox under OpenSuse 11.x</title><content type='html'>IcedTea-Plugin is the standard Java-Pligin for Applets in OpenSuse. It's provided by openjdk. Some application, e.g. ElstarOnline, don't work with IcedTea and need Java-Plugin from SUN. Steps to install SUN's Java-Plugin: &lt;br /&gt;&lt;br /&gt;&lt;div style="color: black;"&gt;&lt;span style="color: orange;"&gt;1)&lt;/span&gt; &lt;span style="color: #f4cccc;"&gt;Download SUN's JRE from http://www.java.com/de/download/. Current version is 1.6.0_21.&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="color: orange;"&gt;2)&lt;/span&gt; &lt;span style="color: #f4cccc;"&gt;Install it. I've installed it under /usr/local/java/jre1.6.0_21&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="color: orange;"&gt;3)&lt;/span&gt; &lt;span style="color: #f4cccc;"&gt;Create the following symbolic link in /usr/lib/browser-plugins/ (root rights are needed)&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #f4cccc;"&gt;sudo ln -s /usr/local/java/jre1.6.0_21/lib/i386/libnpjp2.so /usr/lib/browser-plugins/&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="color: orange;"&gt;4)&lt;/span&gt; &lt;span style="color: #f4cccc;"&gt;Start Firefox and go to the Extras --&amp;gt; Add-ons --&amp;gt; Plugins&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&lt;span style="color: orange;"&gt;5)&lt;/span&gt; &lt;span style="color: #f4cccc;"&gt;Deactivate IcedTea NPR Web Browser Plugin&lt;/span&gt;&lt;/div&gt;&lt;div style="color: black;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #f4cccc;"&gt;Activate (if not yet activated) Java(TM) Plug-in 1.6.0.21&lt;/span&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-7214762088517351087?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/7214762088517351087/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/11/install-sun-java-plugin-fur-firefox.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7214762088517351087'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7214762088517351087'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/11/install-sun-java-plugin-fur-firefox.html' title='Install SUN Java-Plugin für Firefox under OpenSuse 11.x'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-4055019442378479105</id><published>2010-10-27T07:16:00.000-07:00</published><updated>2010-10-28T06:58:09.628-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MyFaces'/><category scheme='http://www.blogger.com/atom/ns#' term='Test'/><category scheme='http://www.blogger.com/atom/ns#' term='PowerMock'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>Tests with PowerMock and MyFaces Test frameworks</title><content type='html'>In one of projects we use &lt;a href="http://mockito.org/"&gt;Mockito &lt;/a&gt;as test framework. It's a great framework having some limitations. We also use different mock objects for JSF environment which come from various sources. A not comfortable mishmash. I have decided to introduce &lt;span style="color: orange;"&gt;PowerMock &lt;/span&gt;and &lt;span style="color: orange;"&gt;MyFaces Test frameworks&lt;/span&gt;. This changing was very effective. First I want to compare two test approaches:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;u&gt;&lt;i&gt;Old approach&lt;/i&gt;:&lt;/u&gt; Utilization of Mockito and JSF / Servlet mocks from "dead" Apache Shale, Spring, ebtam FacesContext.&lt;/li&gt;&lt;li&gt;Disadvantages: Limitations, no mocking of static, final, private classes / methods. Mix of different mocks causes an unconsistent environment. Hacks for the production code.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;&lt;u&gt;New approach&lt;/u&gt;&lt;/i&gt;: Utilization of PowerMock and MyFaces Test frameworks.&lt;/li&gt;&lt;li&gt;Advantages: Mocking of static, final, private classes / methods and more is possible. Unified mock objects and consistent weaving for all fundamental JSF / Servlet pendants.&lt;/li&gt;&lt;/ul&gt;&lt;a href="http://code.google.com/p/powermock/"&gt;PowerMock&lt;/a&gt; extends Mockito by using a custom classloader and bytecode manipulation. It enables mocking of static methods, constructors, final classes and methods, private methods and more. &lt;a href="http://myfaces.apache.org/test/index.html"&gt;MyFaces Test Framework&lt;/a&gt; provides mock object libraries and base classes for creating own test cases. Mocks for the following APIs are provided:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;JavaServer Faces&lt;/li&gt;&lt;li&gt;Servlet&lt;/li&gt;&lt;/ul&gt;The mock netting is as real. Created &lt;span style="color: orange;"&gt;FacesContext&lt;/span&gt; instance will have been registered in the appropriate thread local variable, to simulate what a servlet container would do. The following section shows how to write power JSF 2 tests. For easing use of the new approach there is a class &lt;span style="color: orange;"&gt;JsfServletMock&lt;/span&gt; which provides an access to JSF 2 and Servlet mocks.&lt;br /&gt;&lt;pre class="brush:java"&gt;package com.xyz.webapp.basemock;&lt;br /&gt;&lt;br /&gt;import org.apache.myfaces.test.base.junit4.AbstractJsfTestCase;&lt;br /&gt;import org.apache.myfaces.test.mock.*;&lt;br /&gt;import org.apache.myfaces.test.mock.lifecycle.MockLifecycle;&lt;br /&gt;&lt;br /&gt;public class JsfServletMock extends AbstractJsfTestCase&lt;br /&gt;{&lt;br /&gt;    public MockApplication20 mockApplication;&lt;br /&gt;    public MockExternalContext20 mockExternalContext;&lt;br /&gt;    public MockFacesContext20 mockFacesContext;&lt;br /&gt;    public MockLifecycle mockLifecycle;&lt;br /&gt;    public MockServletContext mockServletContext;&lt;br /&gt;    public MockServletConfig mockServletConfig;&lt;br /&gt;    public MockHttpSession mockHttpSession;&lt;br /&gt;    public MockHttpServletRequest mockHttpServletRequest;&lt;br /&gt;    public MockHttpServletResponse mockHttpServletResponse;&lt;br /&gt;&lt;br /&gt;    public JsfServletMock() {&lt;br /&gt;        try {&lt;br /&gt;            super.setUp();&lt;br /&gt;        } catch (Exception e) {&lt;br /&gt;            throw new IllegalStateException("JSF / Servlet mocks could not be initialized");&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // JSF API&lt;br /&gt;        mockApplication = (MockApplication20) application;&lt;br /&gt;        mockExternalContext = (MockExternalContext20) externalContext;&lt;br /&gt;        mockFacesContext = (MockFacesContext20) facesContext;&lt;br /&gt;        mockLifecycle = lifecycle;&lt;br /&gt;&lt;br /&gt;        // Servlet API&lt;br /&gt;        mockServletContext = servletContext;&lt;br /&gt;        mockServletConfig = config;&lt;br /&gt;        mockHttpSession = session;&lt;br /&gt;        mockHttpServletRequest = request;&lt;br /&gt;        mockHttpServletResponse = response;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;An object of this class can be used in tests per delegation pattern. Define the &lt;span style="color: orange;"&gt;PowerMockRunner &lt;/span&gt;with &lt;span style="color: orange;"&gt;@RunWith&lt;/span&gt; at the beginning. Define classes which static, final, private methods will be mocked / tested with &lt;span style="color: orange;"&gt;@PrepareForTest&lt;/span&gt;. Take an example.&lt;br /&gt;&lt;pre class="brush:java"&gt;import com.xyz.webapp.basemock.JsfServletMock;&lt;br /&gt;import com.xyz.webapp.util.FacesUtils;&lt;br /&gt;import com.xyz.webapp.util.Observer;&lt;br /&gt;import com.xyz.webapp.util.ObserverUtil;&lt;br /&gt;import org.junit.Before;&lt;br /&gt;import org.junit.Test;&lt;br /&gt;import org.junit.runner.RunWith;&lt;br /&gt;import org.mockito.Mock;&lt;br /&gt;import org.powermock.core.classloader.annotations.PrepareForTest;&lt;br /&gt;import org.powermock.modules.junit4.PowerMockRunner;&lt;br /&gt;&lt;br /&gt;import static org.junit.Assert.assertEquals;&lt;br /&gt;import static org.mockito.Matchers.any;&lt;br /&gt;import static org.mockito.Matchers.eq;&lt;br /&gt;import static org.mockito.Mockito.verify;&lt;br /&gt;import static org.powermock.api.mockito.PowerMockito.*;&lt;br /&gt;&lt;br /&gt;@RunWith(PowerMockRunner.class)&lt;br /&gt;@PrepareForTest({FacesUtils.class, ObserverUtil.class})&lt;br /&gt;public class DataExportWorkflowPageTest&lt;br /&gt;{&lt;br /&gt;    private JsfServletMock jsfServletMock;&lt;br /&gt;&lt;br /&gt;    @Mock&lt;br /&gt;    private StatusProfileFinder statusProfileFinder;&lt;br /&gt;&lt;br /&gt;    @Mock&lt;br /&gt;    private Collection&amp;lt;Observer&amp;gt; observers;&lt;br /&gt;&lt;br /&gt;    private DataExportWorkflowPage dewp = new DataExportWorkflowPage();&lt;br /&gt;&lt;br /&gt;    @Before&lt;br /&gt;    public void before() {&lt;br /&gt;        jsfServletMock = new JsfServletMock();&lt;br /&gt;&lt;br /&gt;        dewp.setObservers(observers);&lt;br /&gt;        dewp.setStatusProfileFinder(statusProfileFinder);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Test&lt;br /&gt;    public void initialize() {&lt;br /&gt;        mockStatic(FacesUtils.class);&lt;br /&gt;&lt;br /&gt;        DataExportHistoryForm dehf = mock(DataExportHistoryForm.class);&lt;br /&gt;        DataExportContentForm decf = mock(DataExportContentForm.class);&lt;br /&gt;&lt;br /&gt;        WorkflowData workflowData = mock(WorkflowData.class);&lt;br /&gt;&lt;br /&gt;        when(FacesUtils.accessManagedBean("dataExportHistoryForm")).thenReturn(dehf);&lt;br /&gt;        when(FacesUtils.accessManagedBean("dataExportContentForm")).thenReturn(decf);&lt;br /&gt;&lt;br /&gt;        List&amp;lt;StatusProfile&amp;gt; spList = new ArrayList&amp;lt;StatusProfile&amp;gt;();&lt;br /&gt;        StatusProfile sp1 = new StatusProfile(GenericObjectType.DOCUMENT);&lt;br /&gt;        sp1.setBusinessKey("document");&lt;br /&gt;        spList.add(sp1);&lt;br /&gt;        StatusProfile sp2 = new StatusProfile(GenericObjectType.ACTIVITY);&lt;br /&gt;        sp2.setBusinessKey("activity");&lt;br /&gt;        spList.add(sp2);&lt;br /&gt;        StatusProfile sp3 = new StatusProfile(GenericObjectType.EXPENSE_DOCUMENT_ITEM);&lt;br /&gt;        sp3.setBusinessKey("expense");&lt;br /&gt;        spList.add(sp3);&lt;br /&gt;&lt;br /&gt;        jsfServletMock.mockHttpSession.setAttribute(Constants.SESSION_CLIENT, new Client());&lt;br /&gt;&lt;br /&gt;        when(statusProfileFinder.getAllLimitBy(any(Client.class), eq(Constants.MAX_RESULTS_DEFAULT))).thenReturn(spList);&lt;br /&gt;        when(FacesUtils.accessManagedBean("workflowData")).thenReturn(workflowData);&lt;br /&gt;&lt;br /&gt;        dewp.initialize();&lt;br /&gt;&lt;br /&gt;        verify(observers).add(dehf);&lt;br /&gt;        verify(observers).add(decf);&lt;br /&gt;        verifyNoMoreInteractions(observers);&lt;br /&gt;&lt;br /&gt;        assertEquals(GenericObjectType.DOCUMENT.getId(), dewp.getStatusProfile());&lt;br /&gt;        assertEquals(workflowData, dewp.getWorkflowData());&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;After &lt;span style="color: orange;"&gt;JsfServletMock &lt;/span&gt;instantiation in a method annotated with &lt;span style="color: orange;"&gt;@Before&lt;/span&gt; we have a full access to mock objects. E.g. &lt;span style="color: orange;"&gt;MockHttpSession &lt;/span&gt;can be accessed by &lt;span style="color: orange;"&gt;jsfServletMock.mockHttpSession&lt;/span&gt;. In the example I want to mock the static method &lt;span style="color: orange;"&gt;FacesUtils.accessManagedBean(String)&lt;/span&gt; in the static class. We have to write first&lt;br /&gt;&lt;pre class="brush:java"&gt;mockStatic(FacesUtils.class);&lt;br /&gt;&lt;/pre&gt;to achieve that. And then quite normally&lt;br /&gt;&lt;pre class="brush:java"&gt;when(FacesUtils.accessManagedBean(...)).thenReturn(...);&lt;br /&gt;&lt;/pre&gt;In another small example I use the call&lt;br /&gt;&lt;pre class="brush:java"&gt;verifyStatic();&lt;br /&gt;&lt;/pre&gt;to verify if the subsequent static call got really called. In the example below we verify if&lt;br /&gt;&lt;pre class="brush:java"&gt;ObserverUtil.notifyAll(depd);&lt;br /&gt;&lt;/pre&gt;was called within&lt;br /&gt;&lt;pre class="brush:java"&gt;depd.setProcedureStep2(null);&lt;br /&gt;&lt;/pre&gt;&lt;pre class="brush:java"&gt;@RunWith(PowerMockRunner.class)&lt;br /&gt;@PrepareForTest(ObserverUtil.class)&lt;br /&gt;public class DataExportProcedureDataTest&lt;br /&gt;{&lt;br /&gt;    private DataExportProcedureData depd;&lt;br /&gt;&lt;br /&gt;    @Mock&lt;br /&gt;    private Collection&amp;lt;Observer&amp;gt; observers;&lt;br /&gt;&lt;br /&gt;    @Before&lt;br /&gt;    public void before() {&lt;br /&gt;        depd = new DataExportProcedureData();&lt;br /&gt;        depd.setObservers(observers);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Test&lt;br /&gt;    public void setProcedureStep2() {&lt;br /&gt;        mockStatic(ObserverUtil.class);&lt;br /&gt;&lt;br /&gt;        depd.setProcedureStep2(null);&lt;br /&gt;&lt;br /&gt;        verifyStatic();&lt;br /&gt;        ObserverUtil.notifyAll(depd);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;You see we can do both - mock static methods and verify behaviors.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Bring power to JSF tests! No need for workarounds any more! Keep your production code clean from the test driven stuff!&lt;/b&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-4055019442378479105?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/4055019442378479105/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/10/tests-with-powermock-and-myfaces-test.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/4055019442378479105'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/4055019442378479105'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/10/tests-with-powermock-and-myfaces-test.html' title='Tests with PowerMock and MyFaces Test frameworks'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-8043393353516371946</id><published>2010-10-19T06:59:00.000-07:00</published><updated>2010-10-19T07:09:41.447-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>Global handling of all unchecked / unexpected exceptions in JSF 2</title><content type='html'>JSF 2 specification introduced a new &lt;a href="https://javaserverfaces.dev.java.net/nonav/docs/2.0/javadocs/javax/faces/context/ExceptionHandler.html"&gt;ExceptionHandler API&lt;/a&gt;. All exceptions can be handled globally by an ExceptionHandler instance. Advantage of this centralization is that it allows developers to devise more error handling strategies. I was inspired by the great article of Ed Burns "&lt;a href="http://weblogs.java.net/blog/edburns/archive/2009/09/03/dealing-gracefully-viewexpiredexception-jsf2"&gt;Dealing Gracefully with ViewExpiredException in JSF2&lt;/a&gt;" and developed my own central Exception Handler.&lt;br /&gt;Firstly, we need a factory class that creates and returns a new Exception Handler instance.&lt;br /&gt;&lt;pre class="brush:java"&gt;public class DefaultExceptionHandlerFactory extends ExceptionHandlerFactory {&lt;br /&gt;    private ExceptionHandlerFactory parent;&lt;br /&gt;&lt;br /&gt;    public DefaultExceptionHandlerFactory(ExceptionHandlerFactory parent) {&lt;br /&gt;        this.parent = parent;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public ExceptionHandler getExceptionHandler() {&lt;br /&gt;        ExceptionHandler eh = parent.getExceptionHandler();&lt;br /&gt;        eh = new DefaultExceptionHandler(eh);&lt;br /&gt;&lt;br /&gt;        return eh;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;This factory class has to be registered in&lt;span style="color: orange;"&gt; faces-config.xml&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;factory&amp;gt;&lt;br /&gt;    &amp;lt;exception-handler-factory&amp;gt;&lt;br /&gt;        ip.client.jsftoolkit.commons.DefaultExceptionHandlerFactory&lt;br /&gt;    &amp;lt;/exception-handler-factory&amp;gt;&lt;br /&gt;&amp;lt;/factory&amp;gt;&lt;br /&gt;&lt;/pre&gt;Secondly, we need a class &lt;span style="color: orange;"&gt;DefaultExceptionHandler&lt;/span&gt;. This is the default implementation of the exception handler to catch unchecked / unexpected exceptions in order to proper display.&lt;br /&gt;&lt;pre class="brush:java"&gt;public class DefaultExceptionHandler extends ExceptionHandlerWrapper {&lt;br /&gt;    private static final Log LOG = LogFactory.getLog(DefaultExceptionHandler.class);&lt;br /&gt;&lt;br /&gt;    /** key for session scoped message detail */&lt;br /&gt;    public static final String MESSAGE_DETAIL_KEY = "ip.client.jsftoolkit.messageDetail";&lt;br /&gt;&lt;br /&gt;    private ExceptionHandler wrapped;&lt;br /&gt;&lt;br /&gt;    public DefaultExceptionHandler(ExceptionHandler wrapped) {&lt;br /&gt;        this.wrapped = wrapped;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public ExceptionHandler getWrapped() {&amp;nbsp;&amp;nbsp;&lt;br /&gt;        return this.wrapped;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public void handle() throws FacesException {&lt;br /&gt;        if (fc.isProjectStage(ProjectStage.Development)) {&lt;br /&gt;            // Code for development mode. E.g. let the parent handle exceptions&lt;br /&gt;            getWrapped().handle();&lt;br /&gt;        } else {&lt;br /&gt;            for (Iterator&amp;lt;ExceptionQueuedEvent&amp;gt; i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) {&lt;br /&gt;                ExceptionQueuedEvent event = i.next();&lt;br /&gt;                ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();&lt;br /&gt;&lt;br /&gt;                String redirectPage = null;&lt;br /&gt;                FacesContext fc = FacesContext.getCurrentInstance();&lt;br /&gt;                Throwable t = context.getException();&lt;br /&gt;&lt;br /&gt;                try {&lt;br /&gt;                    if (t instanceof AbortProcessingException) {&lt;br /&gt;                        // about AbortProcessingException see JSF 2 spec.&lt;br /&gt;                        LOG.error("An unexpected exception has occurred by event listener(s)", t);&lt;br /&gt;                        redirectPage = "/views/error.jsf?statusCode=jsftoolkit.exception.UncheckedException";&lt;br /&gt;                        fc.getExternalContext().getSessionMap()&lt;br /&gt;                            .put(DefaultExceptionHandler.MESSAGE_DETAIL_KEY, t.getLocalizedMessage());&lt;br /&gt;                    } else if (t instanceof ViewExpiredException) {&lt;br /&gt;                        if (LOG.isDebugEnabled()) {&lt;br /&gt;                            LOG.debug("View '" + ((ViewExpiredException) t).getViewId() + "' is expired", t);&lt;br /&gt;                        }&lt;br /&gt;&lt;br /&gt;                        ApplicationConfiguration appConfiguration =&lt;br /&gt;                            (ApplicationConfiguration) FacesAccessor.accessManagedBean(&lt;br /&gt;                                ApplicationConfiguration.BEAN_NAME_APPLICATION_CONFIGURATION);&lt;br /&gt;                        HttpSession session = (HttpSession) fc.getExternalContext().getSession(false);&lt;br /&gt;                        if (session != null) {&lt;br /&gt;                            // should not happen&lt;br /&gt;                            session.invalidate();&lt;br /&gt;                        }&lt;br /&gt;&lt;br /&gt;                        if (appConfiguration.getBoolean(ConfigKeys.KEY_LOGOFF_2_LOGOUT_PAGE, false)) {&lt;br /&gt;                            // redirect to the specified logout page&lt;br /&gt;                            redirectPage = "/views/logout.jsf";&lt;br /&gt;                        } else {&lt;br /&gt;                            // redirect to the login page&lt;br /&gt;                            redirectPage = "";&lt;br /&gt;                        }&lt;br /&gt;                    } else if (t instanceof ServiceNotAvailableException) {&lt;br /&gt;                        LOG.error("'" + ((ServiceNotAvailableException) t).getServiceName() + "' is not available", t);&lt;br /&gt;                            redirectPage = "/views/error.jsf?statusCode=jsftoolkit.exception.ServiceNotAvailableException";&lt;br /&gt;                    } else {&lt;br /&gt;                        // custom handling of unexpected exceptions can be done in the method handleUnexpected&lt;br /&gt;                        String messageKey = handleUnexpected(fc, t);&lt;br /&gt;                        redirectPage = "/views/error.jsf?statusCode=" + messageKey;&lt;br /&gt;                        fc.getExternalContext().getSessionMap()&lt;br /&gt;                            .put(DefaultExceptionHandler.MESSAGE_DETAIL_KEY, t.getLocalizedMessage());&lt;br /&gt;                    }&lt;br /&gt;                } finally {&lt;br /&gt;                    i.remove();&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                SecurityPhaseListener spl = new SecurityPhaseListener();&lt;br /&gt;                spl.doRedirect(fc, redirectPage);&lt;br /&gt;&lt;br /&gt;                break;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected String handleUnexpected(FacesContext facesContext, final Throwable t) {&lt;br /&gt;        LOG.error("An unexpected internal error has occurred", t);&lt;br /&gt;&lt;br /&gt;        return "jsftoolkit.exception.UncheckedException";&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The method &lt;span style="color: orange;"&gt;handleUnexpected(FacesContext, Throwable)&lt;/span&gt; can be overwritten in derived classes in order to customization. Handling of various unexpected exceptions can be done there. An example of using:&lt;br /&gt;&lt;pre class="brush:java"&gt;protected String handleUnexpected(FacesContext facesContext, final Throwable t) {&lt;br /&gt;    if (t instanceof IllegalStateException) {&lt;br /&gt;        // some special handling here&lt;br /&gt;        ...&lt;br /&gt;        return "key.exception.IllegalStateException";&lt;br /&gt;    } else {&lt;br /&gt;        return super.handleUnexpected(facesContext, t);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="color: orange;"&gt;SecurityPhaseListener &lt;/span&gt;is the phase listener from &lt;a href="http://ovaraksin.blogspot.com/2010/10/jsf-ajax-redirect-after-session-timeout.html"&gt;my last post&lt;/a&gt; allowing JSF redirects.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-8043393353516371946?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/8043393353516371946/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/10/global-handling-of-all-unchecked.html#comment-form' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/8043393353516371946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/8043393353516371946'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/10/global-handling-of-all-unchecked.html' title='Global handling of all unchecked / unexpected exceptions in JSF 2'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-6949129396803329103</id><published>2010-10-19T05:57:00.000-07:00</published><updated>2011-07-21T07:42:01.216-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='Ajax'/><title type='text'>JSF Ajax redirect after session timeout</title><content type='html'>JSF 2 has a facility to be able to do Ajax redirects. The specification says - &lt;span style="color: orange;"&gt;an element &amp;lt;redirect url="redirect url"/&amp;gt; found in the response causes a redirect to the URL "redirect url"&lt;/span&gt;. JSF component libraries often write other "redirect" elements into response, but the end result is the same - a redirect happens. It works great in case of JSF Ajax redirects.&lt;br /&gt;A web application normally has a security filter - an own solution or from Spring framework or something else. Such security filter does a redirect if user is not authenticated to use requested web resources. This is not an JSF redirect. The filter doesn't pass current request to the &lt;span style="color: orange;"&gt;FacesServlet &lt;/span&gt;at all. Here is an example:&lt;br /&gt;&lt;pre class="brush:java"&gt;public class SecurityFilter implements Filter {&lt;br /&gt;&lt;br /&gt;    private Authenticator authenticator;&lt;br /&gt;    private String loginPage;&lt;br /&gt;    &lt;br /&gt;    public void init(FilterConfig config) throws ServletException {&lt;br /&gt;        ...&lt;br /&gt;        // create an Authenticator&amp;nbsp;&amp;nbsp;&lt;br /&gt;        authenticator = AuthenticatorFactory.createAuthenticator(config);&lt;br /&gt;        loginPage = getLoginPage(config);&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void doFilter(ServletRequest request, ServletResponse response,&lt;br /&gt;        FilterChain chain) throws IOException, ServletException {&lt;br /&gt;        HttpServletRequest hReq = (HttpServletRequest) request;&lt;br /&gt;        HttpServletResponse hRes = (HttpServletResponse) response;&lt;br /&gt;        ...&lt;br /&gt;        // get user roles&lt;br /&gt;        Collection roles = ... &lt;br /&gt;        // get principal&lt;br /&gt;        Principal principal = hReq.getUserPrincipal();&lt;br /&gt;        &lt;br /&gt;        if (!roles.isEmpty() &amp;amp;&amp;amp; principal == null) {&lt;br /&gt;            // user needs to be authenticated&lt;br /&gt;            boolean bRet = authenticator.showLogin(hReq, hRes);&lt;br /&gt;            if (!bRet) {&lt;br /&gt;         // redirect the a login page or error sending&lt;br /&gt;                ...&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;Problem&lt;/b&gt;: indeed an Ajax request is redirected to a specified page after session timeout, but the response can not be proper treated on the client-side. We have a quite regular redirect in this case and the specified page in the response. Client-side Ajax code doesn't expect the entire page coming back.&lt;br /&gt;A possible solution would be to pass "not authenticated" request through &lt;span style="color: orange;"&gt;FacesServlet&lt;/span&gt;. We need to write an &lt;span style="color: orange;"&gt;Authenticator &lt;/span&gt;class which stores the page URL we want to be redirected to in the request scope.&lt;br /&gt;&lt;pre class="brush:java"&gt;public class FormAuthenticator {&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;    public boolean showLogin(HttpServletRequest request, &lt;br /&gt;        HttpServletResponse response, String loginPage) throws IOException {&lt;br /&gt;        ...&lt;br /&gt;        request.setAttribute("web.secfilter.authenticator.showLogin", loginPage);&lt;br /&gt; &lt;br /&gt;        return true;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The method &lt;span style="color: orange;"&gt;showLogin &lt;/span&gt;returns true in order to avoid a redirect by filter. Let us execute the redirect by JSF! The call gets now a third parameter "&lt;span style="color: orange;"&gt;loginPage&lt;/span&gt;".&lt;br /&gt;&lt;pre class="brush:java"&gt;authenticator.showLogin(hReq, hRes, loginPage);&lt;br /&gt;&lt;/pre&gt;If you use Spring security you should have an entry point in your XML configuration file like this one&lt;br /&gt;&lt;pre class="brush:java"&gt;&amp;lt;beans:bean id="authenticationProcessingFilterEntryPoint"&lt;br /&gt;       class="com.xyz.webapp.security.AuthenticationProcessingFilterEntryPoint"&amp;gt;&lt;br /&gt;    &amp;lt;beans:property name="loginFormUrl" value="/login.html"/&amp;gt;&lt;br /&gt;    &amp;lt;beans:property name="serverSideRedirect" value="true"/&amp;gt;&lt;br /&gt;&amp;lt;/beans:bean&amp;gt;&lt;br /&gt;&lt;/pre&gt;The class &lt;span style="color: orange;"&gt;AuthenticationProcessingFilterEntryPoint &lt;/span&gt;is derived from Spring's one&lt;br /&gt;&lt;pre class="brush:java"&gt;/**&lt;br /&gt; * Extended Spring AuthenticationProcessingFilterEntryPoint for playing together with JSF Ajax redirects.&lt;br /&gt; */&lt;br /&gt;public class AuthenticationProcessingFilterEntryPoint extends&lt;br /&gt;    org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint&lt;br /&gt;{&lt;br /&gt;    public static final String ATTRIBUTE_LOGIN_PAGE = "web.secfilter.authenticator.showLogin";&lt;br /&gt;&lt;br /&gt;    public void commence(ServletRequest request, ServletResponse response, AuthenticationException authException)&lt;br /&gt;        throws IOException, ServletException {&lt;br /&gt;&lt;br /&gt;        request.setAttribute(ATTRIBUTE_LOGIN_PAGE, getLoginFormUrl());&lt;br /&gt;        super.commence(request, response, authException);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;On the JSF side we need a special phase listener to do the redirect by &lt;span style="color: orange;"&gt;ExternalContext&lt;/span&gt;. We check at first the buffered page URL in the &lt;span style="color: orange;"&gt;beforePhase&lt;/span&gt;. If it was set - an JSF redirect is needed and will be done.&lt;br /&gt;&lt;pre class="brush:java"&gt;/**&lt;br /&gt; * Phase listener for the Restore View Phase which manages display of login page.&lt;br /&gt; */&lt;br /&gt;public class SecurityPhaseListener implements PhaseListener&lt;br /&gt;{&lt;br /&gt;    private static final Log LOG = LogFactory.getLog(SecurityPhaseListener.class);&lt;br /&gt;&lt;br /&gt;    public void afterPhase(PhaseEvent event) { ; }&lt;br /&gt;&lt;br /&gt;    public void beforePhase(PhaseEvent event) {&lt;br /&gt;        FacesContext fc = event.getFacesContext();&lt;br /&gt;&lt;br /&gt;        String loginPage = (String) fc.getExternalContext().getRequestMap().&lt;br /&gt;            get("web.secfilter.authenticator.showLogin");&lt;br /&gt;        if (StringUtils.isNotBlank(loginPage)) {&lt;br /&gt;            doRedirect(fc, loginPage);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public PhaseId getPhaseId() {&lt;br /&gt;        return PhaseId.RESTORE_VIEW;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Does a regular or ajax redirect.&lt;br /&gt;     */&lt;br /&gt;    public void doRedirect(FacesContext fc, String redirectPage) &lt;br /&gt;        throws FacesException {&lt;br /&gt;        ExternalContext ec = fc.getExternalContext();&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            if (ec.isResponseCommitted()) {&lt;br /&gt;                // redirect is not possible&lt;br /&gt;                return;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            // fix for renderer kit (Mojarra's and PrimeFaces's ajax redirect)&lt;br /&gt;            if ((RequestContext.getCurrentInstance().isAjaxRequest()&lt;br /&gt;                || fc.getPartialViewContext().isPartialRequest())&lt;br /&gt;                &amp;amp;&amp;amp; fc.getResponseWriter() == null&lt;br /&gt;                &amp;amp;&amp;amp; fc.getRenderKit() == null) {&lt;br /&gt;                    ServletResponse response = (ServletResponse) ec.getResponse();&lt;br /&gt;                    ServletRequest request = (ServletRequest) ec.getRequest();&lt;br /&gt;                    response.setCharacterEncoding(request.getCharacterEncoding());&lt;br /&gt;&lt;br /&gt;                    RenderKitFactory factory = (RenderKitFactory)  &lt;br /&gt;                     FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);&lt;br /&gt;&lt;br /&gt;                    RenderKit renderKit = factory.getRenderKit(fc,&lt;br /&gt;                     fc.getApplication().getViewHandler().calculateRenderKitId(fc));&lt;br /&gt;&lt;br /&gt;                    ResponseWriter responseWriter =&lt;br /&gt;                        renderKit.createResponseWriter(&lt;br /&gt;                        response.getWriter(), null, request.getCharacterEncoding());&lt;br /&gt;                        fc.setResponseWriter(responseWriter);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            ec.redirect(ec.getRequestContextPath() + &lt;br /&gt;                (redirectPage != null ? redirectPage : ""));&lt;br /&gt;        } catch (IOException e) {&lt;br /&gt;            LOG.error("Redirect to the specified page '" + &lt;br /&gt;                redirectPage + "' failed");&lt;br /&gt;            throw new FacesException(e);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;It works in both cases - for Ajax and regular request.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-6949129396803329103?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/6949129396803329103/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/10/jsf-ajax-redirect-after-session-timeout.html#comment-form' title='29 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/6949129396803329103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/6949129396803329103'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/10/jsf-ajax-redirect-after-session-timeout.html' title='JSF Ajax redirect after session timeout'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>29</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-4236360024816474919</id><published>2010-10-03T04:01:00.000-07:00</published><updated>2010-10-03T04:02:59.093-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Install Dropbox under OpenSuse 11.3</title><content type='html'>&lt;a href="https://www.dropbox.com/"&gt;Dropbox&lt;/a&gt; is a great online tool to share data between computers. The software for OpenSuse can be found either here &lt;a href="http://software.opensuse.org/113/en"&gt;http://software.opensuse.org/113/en&lt;/a&gt; and installed directly or you have to add this repository&lt;br /&gt;&lt;pre class="brush:java"&gt;http://download.opensuse.org/repositories/openSUSE:/11.3:/Contrib/standard/&lt;br /&gt;&lt;/pre&gt;to the YAST and install it by YAST. After installation open a terminal and type&lt;br /&gt;&lt;pre class="brush:java"&gt;dropbox start -i&lt;br /&gt;&lt;/pre&gt;Just follow the prompts to create an account and choose a dropbox folder on your PC.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-4236360024816474919?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/4236360024816474919/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/10/install-dropbox-under-opensuse-11x.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/4236360024816474919'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/4236360024816474919'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/10/install-dropbox-under-opensuse-11x.html' title='Install Dropbox under OpenSuse 11.3'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-6208918706104597070</id><published>2010-09-21T08:43:00.000-07:00</published><updated>2010-09-21T08:44:58.221-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Install Skype under OpenSuse 11.x</title><content type='html'>If you have installed Skype and it crashes while starting you maybe have an old version of Skype. Here are steps to install Skype on Linux:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1)&lt;/b&gt; Delete currently installed Skype&lt;br /&gt;&lt;div style="background-color: white; color: purple;"&gt;&lt;b&gt;zypper rm skype&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;2)&lt;/b&gt; Delete hidden file &lt;span style="color: orange;"&gt;.skype&lt;/span&gt; in the user home directory.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3)&lt;/b&gt; Make sure you have installed &lt;span style="color: orange;"&gt;libpng12-0&lt;/span&gt; package. Install it by YaST if needed.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4)&lt;/b&gt; Grab the current Skype version from&amp;nbsp;&lt;a href="http://www.skype.com/intl/en/get-skype/on-your-computer/linux/"&gt;http://www.skype.com/intl/en/get-skype/on-your-computer/linux/&lt;/a&gt; and install it. You can also install it directly, e.g.&lt;br /&gt;&lt;div style="background-color: white; color: purple;"&gt;&lt;b&gt;rpm -Uvh http://download.skype.com/linux/skype-2.1.0.81-suse.i586.rpm&lt;/b&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-6208918706104597070?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/6208918706104597070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/09/install-skype-under-opensuse-11x.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/6208918706104597070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/6208918706104597070'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/09/install-skype-under-opensuse-11x.html' title='Install Skype under OpenSuse 11.x'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-7708128791865428609</id><published>2010-09-21T08:19:00.000-07:00</published><updated>2010-09-21T08:20:28.072-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>WLAN with Dell notebook and OpenSuse 11.x</title><content type='html'>Dell notebooks are normally equipped with Broadcom card for WLAN. All 802.11n Broadcom devices need to use the Broadcom STA driver. You need to accomplish the following steps to install such drivers:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1)&lt;/b&gt; Download current drivers from &lt;a href="http://packman.links2linux.de/package/broadcom-wl"&gt;http://packman.links2linux.de/package/broadcom-wl&lt;/a&gt;. You need two drivers. In my case&lt;br /&gt;&lt;div style="background-color: white; color: purple;"&gt;&lt;b&gt;broadcom-wl-5.60.48.36-7.pm.8.5.i586.rpm&lt;/b&gt;&lt;/div&gt;&lt;div style="background-color: white; color: purple;"&gt;&lt;b&gt;broadcom-wl-kmp-default-5.60.48.36_k2.6.34.7_0.2-7.pm.8.5.i586.rpm&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;2)&lt;/b&gt; Open Linux terminal and go to the directory where you downloaded these drivers. Let run two commandos one after another&lt;br /&gt;&lt;div style="background-color: white; color: purple;"&gt;&lt;b&gt;rpm -ivh broadcom-wl-kmp-default-5.60.48.36_k2.6.34.7_0.2-7.pm.8.5.i586.rpm&lt;/b&gt;&lt;/div&gt;&lt;div style="background-color: white; color: purple;"&gt;&lt;b&gt;rpm -ivh broadcom-wl-5.60.48.36-7.pm.8.5.i586.rpm --force&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;3)&lt;/b&gt; Reboot your PC. If you still don't have a WLAN connection go to the YaST and configure WLAN in network devices. You should see at least your drivers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-7708128791865428609?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/7708128791865428609/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/09/wlan-with-dell-notebook-and-opensuse.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7708128791865428609'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/7708128791865428609'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/09/wlan-with-dell-notebook-and-opensuse.html' title='WLAN with Dell notebook and OpenSuse 11.x'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-5875351346923661948</id><published>2010-09-21T07:44:00.000-07:00</published><updated>2010-09-21T08:21:00.573-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Assists in creating consistent equals(), hashCode(), toString()</title><content type='html'>I often see many different implementations for methods &lt;span style="color: orange;"&gt;equals()&lt;/span&gt;, &lt;span style="color: orange;"&gt;hashCode()&lt;/span&gt; and &lt;span style="color: orange;"&gt;toString()&lt;/span&gt;. There is a good and simple approach in Apache Commons Lang which I always use for this purpose. Classes &lt;span style="color: orange;"&gt;EqualsBuilder&lt;/span&gt;, &lt;span style="color: orange;"&gt;HashCodeBuilder&lt;/span&gt; and &lt;span style="color: orange;"&gt;ToStringBuilder&lt;/span&gt; from the package &lt;a href="http://commons.apache.org/lang/api-2.5/org/apache/commons/lang/builder/package-summary.html"&gt;org.apache.commons.lang.builder provide&lt;/a&gt; methods to build consistent and good equals() hashCode() and toString() methods of any class.&lt;br /&gt;We can use either Java reflection or call successive &lt;span style="color: orange;"&gt;append&lt;/span&gt; method for our purpose. Assume we have the following Java class:&lt;br /&gt;&lt;pre class="brush:java"&gt;public class MyClass {&lt;br /&gt;    private String name;&lt;br /&gt;    private int count;&lt;br /&gt;    private List keys;&lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;1)&lt;/b&gt; &lt;i&gt;Use Java reflection:&lt;/i&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;@Override&lt;br /&gt;public boolean equals(final Object obj)&lt;br /&gt;{&lt;br /&gt;    return EqualsBuilder.reflectionEquals(this, obj);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public int hashCode()&lt;br /&gt;{&lt;br /&gt;    return HashCodeBuilder.reflectionHashCode(this);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public String toString()&lt;br /&gt;{&lt;br /&gt;    return ToStringBuilder.reflectionToString(this);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;2)&lt;/b&gt; &lt;i&gt;Include fields manually:&lt;/i&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;@Override&lt;br /&gt;public boolean equals(final Object obj)&lt;br /&gt;{&lt;br /&gt;    if (obj == null) {&lt;br /&gt;        return false;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (obj == this) {&lt;br /&gt;        return true;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (obj.getClass() != getClass()) {&lt;br /&gt;        return false;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    MyClass mc = (MyClass) mc;&lt;br /&gt;&lt;br /&gt;    return new EqualsBuilder().append(name, mc.name).append(count, mc.count).append(keys, mc.keys).isEquals();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public int hashCode()&lt;br /&gt;{&lt;br /&gt;    return new HashCodeBuilder(17, 37).append(name).append(count).append(keys).toHashCode();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public String toString()&lt;br /&gt;{&lt;br /&gt;    return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).&lt;br /&gt;                               append("name", name).append("count", count).append("keys", keys).toString();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;In the second case we have more control and can decide which fields we want to compare and which not. And don't care about data types. They can be primitive, Collection, Map or something else.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-5875351346923661948?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/5875351346923661948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/09/assists-in-creating-consistent-equals.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/5875351346923661948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/5875351346923661948'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/09/assists-in-creating-consistent-equals.html' title='Assists in creating consistent equals(), hashCode(), toString()'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-2037333351760328168</id><published>2010-08-05T03:35:00.000-07:00</published><updated>2010-08-05T10:50:56.665-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>Replacement of h:head in order to fix resources rendering</title><content type='html'>I came up against need to reimplement JSF 2 head component by reason of an issue. I have implemented my custom head tag and achieved more flexibility. I'm going to begin with a history before I will show the code. I'm working with PrimeFaces component library. PrimeFaces comes with predefined CSS settings. Developers often want to overwrite these predefined styles. I do that quite simple - include PrimeFaces resources inside of the head tag and include my own resources close to the body tag. Including of PrimeFaces resources (by &lt;span style="color: orange;"&gt;p:resource&lt;/span&gt;) is actually not necessary for regular requests with full page refresh. But it's necessary if you have partial updates via ajax. An output looks like&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;link rel="stylesheet" type="text/css" href="/icManagement/primefaces_resource/2.0.2/yui/tabview/assets/skins/sam/tabview.css" /&amp;gt;&lt;br /&gt;&amp;lt;link rel="stylesheet" type="text/css" href="/icManagement/primefaces_resource/2.0.2/yui/accordion/assets/skins/sam/accordionview.css" /&amp;gt;&lt;br /&gt;&amp;lt;link rel="stylesheet" type="text/css" href="/icManagement/primefaces_resource/2.0.2/yui/menu/assets/skins/sam/menu.css" /&amp;gt;&lt;br /&gt;&amp;lt;script type="text/javascript" src="/icManagement/primefaces_resource/2.0.2/yui/menu/menu-min.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script type="text/javascript" src="/icManagement/primefaces_resource/2.0.2/yui/json/json-min.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;link type="text/css" rel="stylesheet" href="/icManagement/javax.faces.resource/sky/css/ip-jsftoolkit.css.jsf?ln=themes" /&amp;gt;&lt;br /&gt;&amp;lt;link type="text/css" rel="stylesheet" href="/icManagement/javax.faces.resource/sky/css/incursa-management.css.jsf?ln=themes" /&amp;gt;&lt;br /&gt;&amp;lt;script type="text/javascript" src="/icManagement/javax.faces.resource/ip-jsftoolkit.js.jsf?ln=js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script type="text/javascript" src="/icManagement/javax.faces.resource/incursa-management.js.jsf?ln=js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/pre&gt;Custom CSS, JavaScript files are places after PrimeFaces' one. Well. Mojarra 2.0.2 had an &lt;a href="https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=1443"&gt;issue&lt;/a&gt;, that CSS selectors placed in &lt;span style="color: orange;"&gt;h:head&lt;/span&gt; cannot override styles in implicitly added resources. This issue was fixed in Mojarra 2.0.3. But this bugfixing is not enough because it fixed one issue and caused another one. Why? Often we need &lt;span style="color: orange;"&gt;&amp;lt;meta&amp;gt;&lt;/span&gt; tags to prevent page caching or make sites search engine friendly. Using the &lt;span style="color: orange;"&gt;&amp;lt;link&amp;gt;&lt;/span&gt; tag you can add a "canonical" url to your page and a favicon. The order of these additional tags can be very important. Internet Explorer introduced e.g. a special &lt;span style="color: orange;"&gt;&amp;lt;meta&amp;gt;&lt;/span&gt; tag&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;lt;meta http-equiv="X-UA-Compatible" content="..." /&amp;gt;&lt;br /&gt;&lt;/pre&gt;Content of the &lt;span style="color: orange;"&gt;X-UA-Compatible&lt;/span&gt; &lt;span style="color: orange;"&gt;&amp;lt;meta&amp;gt;&lt;/span&gt; tag helps to control &lt;a href="http://msdn.microsoft.com/en-us/library/cc288325%28VS.85%29.aspx"&gt;document compatibility&lt;/a&gt;. We can specify the rendering engine. For example, inserting this:&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;lt;meta http-equiv="X-UA-Compatible" content="IE=8" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;into the head of a document would force IE8 renders the page using the new standards mode. I often heard "IE8 breaks my site". Add this &lt;span style="color: orange;"&gt;&amp;lt;meta&amp;gt;&lt;/span&gt; tag or HTTP header which can fix the site:&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;lt;meta http-equiv="X-UA-Compatible" content="IE=7" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;It fixes your site, at least until you can sort out the IE8 issues. I use on my pages some great features which are supported by IE8 only. For instance, IE6 / IE7 don't support border color for select elements. You cannot set border color for &lt;span style="color: orange;"&gt;h:selectOneMenu&lt;/span&gt; or &lt;span style="color: orange;"&gt;h:selectManyLisbox&lt;/span&gt;. Unfortunately, IE8 was rendering my pages in IE7 mode. DOCTYPE was ok, but maybe &lt;a href="http://msdn.microsoft.com/en-us/library/cc817573.aspx"&gt;Apache settings&lt;/a&gt; were fault or something else. I decided to put &lt;span style="color: orange;"&gt;content="IE=8"&lt;/span&gt; on all my XHTML pages. But it didn't have any effect. The reason: &lt;span style="color: orange;"&gt;X-UA-Compatible&lt;/span&gt; must be the first child of the head! Internet Explorer doesn't accept this &lt;span style="color: orange;"&gt;&amp;lt;meta&amp;gt;&lt;/span&gt; tag if it's placed after &lt;span style="color: orange;"&gt;&amp;lt;link&amp;gt;&lt;/span&gt; or &lt;span style="color: orange;"&gt;&amp;lt;script&amp;gt;&lt;/span&gt; tags. Many people also encountered the same problem and trey tried making the &lt;span style="color: orange;"&gt;&amp;lt;meta&amp;gt;&lt;/span&gt; tag &lt;span style="color: orange;"&gt;X-UA-Compatible&lt;/span&gt; as the first child of the head to solve this problem. But how could I place this &lt;span style="color: orange;"&gt;&amp;lt;meta&amp;gt;&lt;/span&gt; tag quite at the beginning? The standard &lt;span style="color: orange;"&gt;h:head&lt;/span&gt; tag of the last Mojarra implementation doesn't have this possibility. It always renders at first resources added by JSF 2 facility (don't matter what is placed within head). My output was similar this:&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;link rel="stylesheet" type="text/css" href="/icManagement/primefaces_resource/2.0.2/yui/tabview/assets/skins/sam/tabview.css" /&amp;gt;&lt;br /&gt;&amp;lt;link rel="stylesheet" type="text/css" href="/icManagement/primefaces_resource/2.0.2/yui/accordion/assets/skins/sam/accordionview.css" /&amp;gt;&lt;br /&gt;&amp;lt;link rel="stylesheet" type="text/css" href="/icManagement/primefaces_resource/2.0.2/yui/menu/assets/skins/sam/menu.css" /&amp;gt;&lt;br /&gt;&amp;lt;script type="text/javascript" src="/icManagement/primefaces_resource/2.0.2/yui/menu/menu-min.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script type="text/javascript" src="/icManagement/primefaces_resource/2.0.2/yui/json/json-min.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;meta http-equiv="X-UA-Compatible" content="IE=8"/&amp;gt;&lt;br /&gt;&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/&amp;gt;&lt;br /&gt;&amp;lt;meta http-equiv="pragma" content="no-cache"/&amp;gt;&lt;br /&gt;&amp;lt;meta http-equiv="cache-control" content="no-cache"/&amp;gt;&lt;br /&gt;&amp;lt;meta http-equiv="expires" content="0"/&amp;gt;&lt;br /&gt;&lt;/pre&gt;You see, the standrad &lt;span style="color: orange;"&gt;h:head&lt;/span&gt; is not flexible enough. Oracle ADF has a special &lt;span style="color: orange;"&gt;&amp;lt;af:document&amp;gt;&lt;/span&gt; tag where you can use the facet "&lt;span style="color: orange;"&gt;metaContainer&lt;/span&gt;" of the &lt;span style="color: orange;"&gt;&amp;lt;af:document&amp;gt;&lt;/span&gt; to output the tags in the right place. Eureka! We need facets in the head component for right order controling of rendered resources. Let's write a custom head component:&lt;br /&gt;&lt;pre class="brush:java"&gt;public class Head extends UIOutput&lt;br /&gt;{&lt;br /&gt; public static final String COMPONENT_TYPE = "ip.client.jsftoolkit.components.Head";&lt;br /&gt; public static final String COMPONENT_FAMILY = "ip.client.jsftoolkit.components";&lt;br /&gt; private static final String DEFAULT_RENDERER = "ip.client.jsftoolkit.components.HeadRenderer";&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Properties that are tracked by state saving.&lt;br /&gt;  */&lt;br /&gt; protected enum PropertyKeys&lt;br /&gt; {&lt;br /&gt;  title, shortcutIcon;&lt;br /&gt;&lt;br /&gt;  String toString;&lt;br /&gt;&lt;br /&gt;  PropertyKeys(String toString)&lt;br /&gt;  {&lt;br /&gt;   this.toString = toString;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  PropertyKeys()&lt;br /&gt;  {&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public String toString()&lt;br /&gt;  {&lt;br /&gt;   return ((this.toString != null) ? this.toString : super.toString());&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public Head()&lt;br /&gt; {&lt;br /&gt;  setRendererType(DEFAULT_RENDERER);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getFamily()&lt;br /&gt; {&lt;br /&gt;  return COMPONENT_FAMILY;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getTitle()&lt;br /&gt; {&lt;br /&gt;  return (String) getStateHelper().eval(PropertyKeys.title, null);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setTitle(String title)&lt;br /&gt; {&lt;br /&gt;  getStateHelper().put(PropertyKeys.title, title);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getShortcutIcon()&lt;br /&gt; {&lt;br /&gt;  return (String) getStateHelper().eval(PropertyKeys.shortcutIcon, null);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setShortcutIcon(String shortcutIcon)&lt;br /&gt; {&lt;br /&gt;  getStateHelper().put(PropertyKeys.shortcutIcon, shortcutIcon);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;I took "&lt;span style="color: orange;"&gt;title&lt;/span&gt;" and "&lt;span style="color: orange;"&gt;shortcutIcon&lt;/span&gt;" attributes to the head component in order to achieve more convenience by using. Now the renderer:&lt;br /&gt;&lt;pre class="brush:java"&gt;import java.io.IOException;&lt;br /&gt;import java.util.ListIterator;&lt;br /&gt;import javax.faces.component.UIComponent;&lt;br /&gt;import javax.faces.component.UIViewRoot;&lt;br /&gt;import javax.faces.context.FacesContext;&lt;br /&gt;import javax.faces.context.ResponseWriter;&lt;br /&gt;import javax.faces.render.Renderer;&lt;br /&gt;&lt;br /&gt;public class HeadRenderer extends Renderer&lt;br /&gt;{&lt;br /&gt; public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException&lt;br /&gt; {&lt;br /&gt;  ResponseWriter writer = facesContext.getResponseWriter();&lt;br /&gt;  writer.startElement("head", component);&lt;br /&gt;&lt;br /&gt;  UIComponent first = component.getFacet("first");&lt;br /&gt;  if (first != null) {&lt;br /&gt;   first.encodeAll(facesContext);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  UIViewRoot viewRoot = facesContext.getViewRoot();&lt;br /&gt;  ListIterator&amp;lt;UIComponent&amp;gt; iter = (viewRoot.getComponentResources(facesContext, "head")).listIterator();&lt;br /&gt;  while (iter.hasNext()) {&lt;br /&gt;   UIComponent resource = (UIComponent) iter.next();&lt;br /&gt;   resource.encodeAll(facesContext);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException&lt;br /&gt; {&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException&lt;br /&gt; {&lt;br /&gt;  ResponseWriter writer = facesContext.getResponseWriter();&lt;br /&gt;  Head head = (Head) component;&lt;br /&gt;&lt;br /&gt;  UIComponent last = component.getFacet("last");&lt;br /&gt;  if (last != null) {&lt;br /&gt;   last.encodeAll(facesContext);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (head.getTitle() != null) {&lt;br /&gt;   writer.startElement("title", null);&lt;br /&gt;   writer.write(head.getTitle());&lt;br /&gt;   writer.endElement("title");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (head.getShortcutIcon() != null) {&lt;br /&gt;   writer.startElement("link", null);&lt;br /&gt;   writer.writeAttribute("rel", "shortcut icon", null);&lt;br /&gt;   writer.writeAttribute("href", head.getShortcutIcon(), null);&lt;br /&gt;   writer.endElement("link");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  writer.endElement("head");&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;I introduced two facets called "&lt;span style="color: orange;"&gt;first&lt;/span&gt;" and "&lt;span style="color: orange;"&gt;last&lt;/span&gt;". The resource rendering order with this approach:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Resources placed into "&lt;span style="color: orange;"&gt;first&lt;/span&gt;" facet.&lt;/li&gt;&lt;li&gt;Resources added by JSF 2 facility.&lt;/li&gt;&lt;li&gt;Resources placed into "&lt;span style="color: orange;"&gt;last&lt;/span&gt;" facet.&lt;/li&gt;&lt;li&gt;Page title and shortcut icon.&lt;/li&gt;&lt;/ol&gt;The new component and its tag have be registered as usual in faces-config and taglib XMLs.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;renderer&amp;gt;&lt;br /&gt; &amp;lt;component-family&amp;gt;ip.client.jsftoolkit.components&amp;lt;/component-family&amp;gt;&lt;br /&gt; &amp;lt;renderer-type&amp;gt;ip.client.jsftoolkit.components.HeadRenderer&amp;lt;/renderer-type&amp;gt;&lt;br /&gt; &amp;lt;renderer-class&amp;gt;ip.client.jsftoolkit.components.head.HeadRenderer&amp;lt;/renderer-class&amp;gt;&lt;br /&gt;&amp;lt;/renderer&amp;gt;&lt;br /&gt;&amp;lt;component&amp;gt;&lt;br /&gt; &amp;lt;component-type&amp;gt;ip.client.jsftoolkit.components.Head&amp;lt;/component-type&amp;gt;&lt;br /&gt; &amp;lt;component-class&amp;gt;ip.client.jsftoolkit.components.head.Head&amp;lt;/component-class&amp;gt;&lt;br /&gt;&amp;lt;/component&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;tag&amp;gt;&lt;br /&gt; &amp;lt;tag-name&amp;gt;head&amp;lt;/tag-name&amp;gt;&lt;br /&gt; &amp;lt;component&amp;gt;&lt;br /&gt;  &amp;lt;component-type&amp;gt;ip.client.jsftoolkit.components.Head&amp;lt;/component-type&amp;gt;&lt;br /&gt;  &amp;lt;renderer-type&amp;gt;ip.client.jsftoolkit.components.HeadRenderer&amp;lt;/renderer-type&amp;gt;&lt;br /&gt; &amp;lt;/component&amp;gt;&lt;br /&gt;&amp;lt;/tag&amp;gt;&lt;br /&gt;&lt;/pre&gt;Using on page:&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt;   xmlns:f="http://java.sun.com/jsf/core"&lt;br /&gt;   xmlns:h="http://java.sun.com/jsf/html"&lt;br /&gt;   xmlns:ui="http://java.sun.com/jsf/facelets"&lt;br /&gt;   xmlns:jtcomp="http://ip.client/ip-jsftoolkit/components"&amp;gt;&lt;br /&gt;&amp;lt;f:view contentType="text/html" locale="#{userSettings.locale}"&amp;gt;&lt;br /&gt;&amp;lt;ui:insert name="metadata"/&amp;gt;&lt;br /&gt;&amp;lt;jtcomp:head title="#{messageParameters['frameworkTitle']}" shortcutIcon="#{request.contextPath}/favicon.ico"&amp;gt;&lt;br /&gt;  &amp;lt;f:facet name="first"&amp;gt;&lt;br /&gt;    &amp;lt;meta http-equiv="X-UA-Compatible" content="IE=8"/&amp;gt;&lt;br /&gt;    &amp;lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/&amp;gt;&lt;br /&gt;    &amp;lt;meta http-equiv="pragma" content="no-cache"/&amp;gt;&lt;br /&gt;    &amp;lt;meta http-equiv="cache-control" content="no-cache"/&amp;gt;&lt;br /&gt;    &amp;lt;meta http-equiv="expires" content="0"/&amp;gt;&lt;br /&gt;  &amp;lt;/f:facet&amp;gt;&lt;br /&gt;  &amp;lt;f:facet name="last"&amp;gt;&lt;br /&gt;    &amp;lt;style type="text/css"&amp;gt;&lt;br /&gt;      html, body {&lt;br /&gt;        width: 100%;&lt;br /&gt;        height: 100%;&lt;br /&gt;        margin: 0px;&lt;br /&gt;      }&lt;br /&gt;    &amp;lt;/style&amp;gt;&lt;br /&gt;    &amp;lt;script type="text/javascript"&amp;gt;...&amp;lt;/script&amp;gt;&lt;br /&gt;  &amp;lt;/f:facet&amp;gt;&lt;br /&gt;  &amp;lt;ui:insert name="resources-pf"/&amp;gt;&lt;br /&gt;&amp;lt;/jtcomp:head&amp;gt;&lt;br /&gt;&amp;lt;h:body&amp;gt;&lt;br /&gt;...&lt;br /&gt; &amp;lt;ui:insert name="resources-app"/&amp;gt;&lt;br /&gt;&amp;lt;/h:body&amp;gt;&lt;br /&gt;&amp;lt;/f:view&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;Generated output in the right defined order:&lt;br /&gt;&lt;pre class="brush:html"&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;&amp;lt;head&amp;gt;&lt;br /&gt;  &amp;lt;meta http-equiv="X-UA-Compatible" content="IE=8" /&amp;gt;&lt;br /&gt;  &amp;lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&amp;gt;&lt;br /&gt;  &amp;lt;meta http-equiv="pragma" content="no-cache" /&amp;gt;&lt;br /&gt;  &amp;lt;meta http-equiv="cache-control" content="no-cache" /&amp;gt;&lt;br /&gt;  &amp;lt;meta http-equiv="expires" content="0" /&amp;gt;&lt;br /&gt;  &lt;br /&gt;  &amp;lt;link rel="stylesheet" type="text/css" href="/icManagement/primefaces_resource/2.0.2/yui/tabview/assets/skins/sam/tabview.css" /&amp;gt;&lt;br /&gt;  &amp;lt;link rel="stylesheet" type="text/css" href="/icManagement/primefaces_resource/2.0.2/yui/accordion/assets/skins/sam/accordionview.css" /&amp;gt;&lt;br /&gt;  &amp;lt;link rel="stylesheet" type="text/css" href="/icManagement/primefaces_resource/2.0.2/yui/menu/assets/skins/sam/menu.css" /&amp;gt;&lt;br /&gt;  &amp;lt;script type="text/javascript" src="/icManagement/primefaces_resource/2.0.2/yui/menu/menu-min.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;  &amp;lt;script type="text/javascript" src="/icManagement/primefaces_resource/2.0.2/yui/json/json-min.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;  ...&lt;br /&gt;  &amp;lt;link type="text/css" rel="stylesheet" href="/icManagement/javax.faces.resource/sky/css/ip-jsftoolkit.css.jsf?ln=themes" /&amp;gt;&lt;br /&gt;  &amp;lt;link type="text/css" rel="stylesheet" href="/icManagement/javax.faces.resource/sky/css/incursa-management.css.jsf?ln=themes" /&amp;gt;&lt;br /&gt;  &amp;lt;script type="text/javascript" src="/icManagement/javax.faces.resource/ip-jsftoolkit.js.jsf?ln=js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;  &amp;lt;script type="text/javascript" src="/icManagement/javax.faces.resource/incursa-management.js.jsf?ln=js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;  &amp;lt;style type="text/css"&amp;gt;&lt;br /&gt;   html, body {&lt;br /&gt;    width: 100%;&lt;br /&gt;    height: 100%;&lt;br /&gt;    margin: 0px;&lt;br /&gt;   }&lt;br /&gt;  &amp;lt;/style&amp;gt;&lt;br /&gt;  &amp;lt;script type="text/javascript"&amp;gt;...&amp;lt;/script&amp;gt;&lt;br /&gt;  &amp;lt;title&amp;gt;Management Client&amp;lt;/title&amp;gt;&lt;br /&gt;  &amp;lt;link rel="shortcut icon" href="/icManagement/favicon.ico" /&amp;gt;&lt;br /&gt;  &amp;lt;/head&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;Cool? :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-2037333351760328168?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/2037333351760328168/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/08/replacement-of-hhead-in-order-to-fix.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2037333351760328168'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/2037333351760328168'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/08/replacement-of-hhead-in-order-to-fix.html' title='Replacement of h:head in order to fix resources rendering'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-4799157496130142311</id><published>2010-08-04T03:55:00.001-07:00</published><updated>2010-08-04T03:55:55.966-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Apache POI'/><title type='text'>Metadata extraction from MS Outlook messages</title><content type='html'>&lt;a href="http://ovaraksin.blogspot.com/2010/07/metadata-extraction-from-ms-office.html"&gt;In the previous post&lt;/a&gt; I showed how to extract metadata from MS Office documents. In this post I will show how to extract metadata from MS Outlook messages. There are some solutions like &lt;a href="http://poi.apache.org/hsmf/index.html"&gt;Apache POI-HSMF&lt;/a&gt; oder &lt;a href="http://auxilii.com/msgparser/"&gt;msgparser&lt;/a&gt;. But all these solutions are not universal enough, API are restricted and algorithm are not reliable because they try to find / match some subsequences without deep knowledge about MSG file structure. My task was to extract the properties "&lt;span style="color: orange;"&gt;Subject&lt;/span&gt;", "&lt;span style="color: orange;"&gt;From&lt;/span&gt;", "&lt;span style="color: orange;"&gt;To&lt;/span&gt;", "&lt;span style="color: orange;"&gt;Cc&lt;/span&gt;", "&lt;span style="color: orange;"&gt;Sent&lt;/span&gt;", "&lt;span style="color: orange;"&gt;Received&lt;/span&gt;". Well. Let's start with &lt;span style="color: orange;"&gt;MsgExtractor&lt;/span&gt;. The method to be called after instantiation is &lt;span style="color: orange;"&gt;parseMetaData&lt;/span&gt;. The idea is similar to the one for MS Office documents.&lt;br /&gt;&lt;pre class="brush:java"&gt;public class MsgExtractor&lt;br /&gt;{&lt;br /&gt; public static final String PROPERTY_SUBJECT = "Subject";&lt;br /&gt; public static final String PROPERTY_FROM = "From";&lt;br /&gt; public static final String PROPERTY_TO = "To";&lt;br /&gt; public static final String PROPERTY_CC = "Cc";&lt;br /&gt; public static final String PROPERTY_SENT = "Sent";&lt;br /&gt; public static final String PROPERTY_RECEIVED = "Received";&lt;br /&gt;&lt;br /&gt; private static final Map TEMPLATE_PROPERTY_2_GET_METHODS;&lt;br /&gt;&lt;br /&gt; static {&lt;br /&gt;  TEMPLATE_PROPERTY_2_GET_METHODS = new HashMap();&lt;br /&gt;  TEMPLATE_PROPERTY_2_GET_METHODS.put(PROPERTY_SUBJECT, "getSubject");&lt;br /&gt;  TEMPLATE_PROPERTY_2_GET_METHODS.put(PROPERTY_FROM, "getDisplayFrom");&lt;br /&gt;  TEMPLATE_PROPERTY_2_GET_METHODS.put(PROPERTY_TO, "getDisplayTo");&lt;br /&gt;  TEMPLATE_PROPERTY_2_GET_METHODS.put(PROPERTY_CC, "getDisplayCc");&lt;br /&gt;  TEMPLATE_PROPERTY_2_GET_METHODS.put(PROPERTY_SENT, "getClientSubmitTime");&lt;br /&gt;  TEMPLATE_PROPERTY_2_GET_METHODS.put(PROPERTY_RECEIVED, "getMessageDeliveryTime");&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; final String[] properties;&lt;br /&gt;&lt;br /&gt; public MsgExtractor(final String[] properties)&lt;br /&gt; {&lt;br /&gt;  this.properties = (properties == null ? new String[] {} : properties);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public Map parseMetaData(final byte[] data) throws MetaDataExtractionException&lt;br /&gt; {&lt;br /&gt;  // check at first whether byte array data is null and throw an exception if it's null&lt;br /&gt;  ...&lt;br /&gt;  &lt;br /&gt;  if (properties.length == 0) {&lt;br /&gt;   return Collections.EMPTY_MAP;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  Map metaData = new HashMap();&lt;br /&gt;  OutlookMessage outlookMessage = new OutlookMessage(new ByteArrayInputStream(data));&lt;br /&gt;&lt;br /&gt;  try {&lt;br /&gt;   for (int i = 0; i &amp;lt; properties.length; i++) {&lt;br /&gt;    Object propertyValue = null;&lt;br /&gt;    String strMethod = (String) TEMPLATE_PROPERTY_2_GET_METHODS.get(properties[i]);&lt;br /&gt;    if (strMethod != null) {&lt;br /&gt;     Method method = OutlookMessage.class.getMethod(strMethod, (Class[]) null);&lt;br /&gt;     propertyValue = method.invoke(outlookMessage, (Object[]) (Object[]) null);&lt;br /&gt;    } else {&lt;br /&gt;     LOG.warn("No Get-Method to the MAPI-Property was found for the defined template property '"&lt;br /&gt;              + properties[i] + "'");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // buffer property values&lt;br /&gt;    metaData.put(properties[i], propertyValue);&lt;br /&gt;   }&lt;br /&gt;  } catch (final Exception e) {&lt;br /&gt;   // failed to extract meta data ==&amp;gt; error handling&lt;br /&gt;   ...&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return metaData;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The main class is &lt;span style="color: orange;"&gt;OutlookMessage &lt;/span&gt;which hides a magic work. It looks as follows&lt;br /&gt;&lt;pre class="brush:java"&gt;import java.io.File;&lt;br /&gt;import java.io.FileInputStream;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.InputStream;&lt;br /&gt;import java.io.UnsupportedEncodingException;&lt;br /&gt;import java.util.Date;&lt;br /&gt;import java.util.Iterator;&lt;br /&gt;&lt;br /&gt;import org.apache.commons.io.EndianUtils;&lt;br /&gt;import org.apache.commons.lang.ArrayUtils;&lt;br /&gt;import org.apache.commons.lang.StringUtils;&lt;br /&gt;import org.apache.commons.logging.Log;&lt;br /&gt;import org.apache.commons.logging.LogFactory;&lt;br /&gt;import org.apache.poi.poifs.filesystem.DirectoryEntry;&lt;br /&gt;import org.apache.poi.poifs.filesystem.DocumentEntry;&lt;br /&gt;import org.apache.poi.poifs.filesystem.DocumentInputStream;&lt;br /&gt;import org.apache.poi.poifs.filesystem.Entry;&lt;br /&gt;import org.apache.poi.poifs.filesystem.POIFSFileSystem;&lt;br /&gt;&lt;br /&gt;**&lt;br /&gt; * Reads an Outlook MSG File in and provides hooks into its data structure. Some hints to the structure were found under&lt;br /&gt; *&lt;br /&gt; * &amp;lt;ul&amp;gt;&lt;br /&gt; *   &amp;lt;li&amp;gt;http://www.fileformat.info/format/outlookmsg/&amp;lt;/li&amp;gt;&lt;br /&gt; *   &amp;lt;li&amp;gt;http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/&amp;lt;/li&amp;gt;&lt;br /&gt; *   &amp;lt;li&amp;gt;http://www.tech-archive.net/Archive/Development/microsoft.public.win32.programmer.ole/2006-08/msg00123.html&lt;br /&gt; *   &amp;lt;/li&amp;gt;&lt;br /&gt; * &amp;lt;/ul&amp;gt;&lt;br /&gt; *&lt;br /&gt; */&lt;br /&gt;public class OutlookMessage&lt;br /&gt;{&lt;br /&gt; private static final Log LOG = LogFactory.getLog(OutlookMessage.class);&lt;br /&gt;&lt;br /&gt; /** id for the mapi property "subject" */&lt;br /&gt; private static final int PROP_SUBJECT = 0x0037;&lt;br /&gt;&lt;br /&gt; /** id for the mapi property "display from" */&lt;br /&gt; private static final int PROP_DISPLAY_FROM = 0x0C1A;&lt;br /&gt;&lt;br /&gt; /** id for the mapi property "display to" */&lt;br /&gt; private static final int PROP_DISPLAY_TO = 0x0E04;&lt;br /&gt;&lt;br /&gt; /** id for the mapi property "display cc" */&lt;br /&gt; private static final int PROP_DISPLAY_CC = 0x0E03;&lt;br /&gt;&lt;br /&gt; /** reversed endian format of the property id "client submit time" */&lt;br /&gt; private static final byte[] PROP_CLIENT_SUBMIT_TIME = {0x40, 0x00, 0x39, 0x00};&lt;br /&gt;&lt;br /&gt; /** reversed endian format of the property id "message delivery time" */&lt;br /&gt; private static final byte[] PROP_MESSAGE_DELIVERY_TIME = {0x40, 0x00, 0x06, 0x0E};&lt;br /&gt;&lt;br /&gt; private String subject;&lt;br /&gt;&lt;br /&gt; private String displayFrom;&lt;br /&gt;&lt;br /&gt; private String displayTo;&lt;br /&gt;&lt;br /&gt; private String displayCc;&lt;br /&gt;&lt;br /&gt; private Date clientSubmitTime;&lt;br /&gt;&lt;br /&gt; private Date messageDeliveryTime;&lt;br /&gt;&lt;br /&gt; public OutlookMessage(String filename) throws IOException&lt;br /&gt; {&lt;br /&gt;  this(new FileInputStream(new File(filename)));&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public OutlookMessage(InputStream in)&lt;br /&gt; {&lt;br /&gt;  try {&lt;br /&gt;   POIFSFileSystem fs = new POIFSFileSystem(in);&lt;br /&gt;   initMapiProperties(fs);&lt;br /&gt;  } catch (IOException ioe) {&lt;br /&gt;   LOG.warn("Some properties could be not parsed from given MSG message " + ioe);&lt;br /&gt;  } finally {&lt;br /&gt;   if (in != null) {&lt;br /&gt;    try {&lt;br /&gt;     in.close();&lt;br /&gt;    } catch (IOException e) {&lt;br /&gt;     ;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private void initMapiProperties(POIFSFileSystem fs) throws IOException&lt;br /&gt; {&lt;br /&gt;  DirectoryEntry root = fs.getRoot();&lt;br /&gt;&lt;br /&gt;  for (Iterator iter = root.getEntries(); iter.hasNext();) {&lt;br /&gt;   Entry entry = (Entry) iter.next();&lt;br /&gt;   if (!(entry instanceof DocumentEntry)) {&lt;br /&gt;    continue;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   String entryName = entry.getName();&lt;br /&gt;   if (entryName == null) {&lt;br /&gt;    continue;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // parse MAPI properties&lt;br /&gt;   if (entryName.startsWith("__substg1.0_")) {&lt;br /&gt;    byte[] substgBytes = getBytes((DocumentEntry) entry);&lt;br /&gt;&lt;br /&gt;    int id = Integer.parseInt(entryName.substring(12, 16), 16);&lt;br /&gt;    int type = Integer.parseInt(entryName.substring(16, 20), 16);&lt;br /&gt;&lt;br /&gt;    if (id == PROP_SUBJECT) {&lt;br /&gt;     // subject&lt;br /&gt;     this.subject = getString(substgBytes, isUnicodeString(type));&lt;br /&gt;    } else if (id == PROP_DISPLAY_FROM) {&lt;br /&gt;     // display from&lt;br /&gt;     this.displayFrom = getString(substgBytes, isUnicodeString(type));&lt;br /&gt;    } else if (id == PROP_DISPLAY_TO) {&lt;br /&gt;     // display to&lt;br /&gt;     this.displayTo = getString(substgBytes, isUnicodeString(type));&lt;br /&gt;    } else if (id == PROP_DISPLAY_CC) {&lt;br /&gt;     // display cc&lt;br /&gt;     this.displayCc = getString(substgBytes, isUnicodeString(type));&lt;br /&gt;    }&lt;br /&gt;   } else if (entryName.startsWith("__properties_version1.0")) {&lt;br /&gt;    byte[] propBytes = getBytes((DocumentEntry) entry);&lt;br /&gt;    int offset = 0;&lt;br /&gt;    int bytesLength = propBytes.length;&lt;br /&gt;&lt;br /&gt;    while (offset + 16 &amp;lt;= bytesLength) {&lt;br /&gt;     byte[] propId = read4(propBytes, offset);&lt;br /&gt;&lt;br /&gt;     if (compare(propId, PROP_CLIENT_SUBMIT_TIME)) {&lt;br /&gt;      // read value&lt;br /&gt;      this.clientSubmitTime = getDate(propBytes, offset);&lt;br /&gt;     } else if (compare(propId, PROP_MESSAGE_DELIVERY_TIME)) {&lt;br /&gt;      // read value&lt;br /&gt;      this.messageDeliveryTime = getDate(propBytes, offset);&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     offset = offset + 16;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private byte[] getBytes(DocumentEntry docEntry) throws IOException&lt;br /&gt; {&lt;br /&gt;  DocumentInputStream dis = new DocumentInputStream(docEntry);&lt;br /&gt;  byte[] propBytes = new byte[dis.available()];&lt;br /&gt;&lt;br /&gt;  try {&lt;br /&gt;   byte[] bytes = new byte[4096];&lt;br /&gt;   int readCount;&lt;br /&gt;   int curPosition = 0;&lt;br /&gt;   while ((readCount = dis.read(bytes)) &amp;gt; -1) {&lt;br /&gt;    System.arraycopy(bytes, 0, propBytes, curPosition, readCount);&lt;br /&gt;    curPosition = curPosition + readCount;&lt;br /&gt;   }&lt;br /&gt;  } finally {&lt;br /&gt;   dis.close();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return propBytes;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private String getString(byte[] bytes, boolean isUnicode)&lt;br /&gt; {&lt;br /&gt;  if (ArrayUtils.isEmpty(bytes)) {&lt;br /&gt;   return null;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  try {&lt;br /&gt;   String str;&lt;br /&gt;   if (isUnicode) {&lt;br /&gt;    str = new String(bytes, 0, bytes.length, "UTF-16LE");&lt;br /&gt;   } else {&lt;br /&gt;    str = new String(bytes, 0, bytes.length, "ISO8859_1");&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   int len = str.length();&lt;br /&gt;   while (len &amp;gt; 0 &amp;amp;&amp;amp; str.charAt(len - 1) == '\0') {&lt;br /&gt;    len--;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   if (len != str.length()) {&lt;br /&gt;    str = str.substring(0, len);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   if (StringUtils.isBlank(str)) {&lt;br /&gt;    str = null;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return str;&lt;br /&gt;  } catch (UnsupportedEncodingException ignore) {&lt;br /&gt;   ;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return null;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private boolean isUnicodeString(int type)&lt;br /&gt; {&lt;br /&gt;  return (type == 0x001F ? true : false); // for not unicode string type = 0x001E&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private byte[] read4(byte[] data, int offset)&lt;br /&gt; {&lt;br /&gt;  byte[] readBytes = new byte[4];&lt;br /&gt;  System.arraycopy(data, offset, readBytes, 0, 4);&lt;br /&gt;&lt;br /&gt;  return readBytes;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private byte[] read8(byte[] data, int offset)&lt;br /&gt; {&lt;br /&gt;  byte[] readBytes = new byte[8];&lt;br /&gt;  System.arraycopy(data, offset, readBytes, 0, 8);&lt;br /&gt;&lt;br /&gt;  return readBytes;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private boolean compare(byte[] b1, byte[] b2)&lt;br /&gt; {&lt;br /&gt;  for (int i = 0; i &amp;lt; b1.length; ++i) {&lt;br /&gt;   if (b1[i] != b2[i]) {&lt;br /&gt;    return false;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return true;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private Date getDate(byte[] propBytes, int offset)&lt;br /&gt; {&lt;br /&gt;  // read value&lt;br /&gt;  byte[] value = read8(propBytes, offset + 8);&lt;br /&gt;&lt;br /&gt;  // convert to long (reverse Endian format)&lt;br /&gt;  long time = EndianUtils.readSwappedLong(value, 0);&lt;br /&gt;&lt;br /&gt;  // FILETIME 64-bit int number of 100ns periods since Jan 1, 1601 ==&amp;gt;&lt;br /&gt;  // convert ns to ms and substruct milliseconds between 1/1/1601 and 1/1/1970&lt;br /&gt;  time = (time / 10 / 1000) - 1000L * 60L * 60L * 24L * (365L * 369L + 89L);&lt;br /&gt;&lt;br /&gt;  return new Date(time);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; // getter&lt;br /&gt;&lt;br /&gt; public String getSubject() {return subject;}&lt;br /&gt;&lt;br /&gt; public String getDisplayFrom() {return displayFrom;}&lt;br /&gt;&lt;br /&gt; public String getDisplayTo() {return displayTo;}&lt;br /&gt;&lt;br /&gt; public String getDisplayCc() {return displayCc;}&lt;br /&gt;&lt;br /&gt; public Date getClientSubmitTime() {return clientSubmitTime;}&lt;br /&gt;&lt;br /&gt; public Date getMessageDeliveryTime() {return messageDeliveryTime;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Parse of MAPI properties in the stream &lt;span style="color: orange;"&gt;__substg1.0_&lt;/span&gt; don't cause any problems. That are quite normally strings. But some properties are in a binary stream called &lt;span style="color: orange;"&gt;__properties_version1.0&lt;/span&gt;. This is the most interesting stream.&lt;br /&gt;&lt;i style="background-color: #741b47; color: white;"&gt;Hint to the structure&lt;/i&gt; of &lt;span style="color: orange;"&gt;__properties_version1.0&lt;/span&gt;: Each MAPI property has a well documented hex id, available on the MSDN site. For example, the property PR_CLIENT_SUBMIT_TIME has an identifier of 0x00390040. If you open the properties stream and work with 16 byte rows, divided into two 8 byte sections (just like a hex editor), you will see that the property identifier is in the first 8 byte section and the value is in the second. The trick is to reverse the Endian of the property ID. So the ID for the PR_CLIENT_SUBMIT_TIME property becomes 40 00 39 00. Locate this hex block and you will have the value (in Big Endian FILETIME format) in the next 8 byte section.&lt;br /&gt;&lt;br /&gt;With a little code extension you can extract "creation time" (reversed endian format of the property id {0x40, 0x00, 0x07, 0x30}), "last modification time" (reversed endian format of the property id {0x40, 0x00, 0x08, 0x30}) or all other imaginable properties. You can use a &lt;a href="http://www.softrecipe.com/Internet/E-mail/viewer_for_ms_outlook_messages.html"&gt;Viewer for MS Outlook Messages&lt;/a&gt; to find out proper endian formats. I have tried this approach for MSG files produced with MS Outlook 2003 / 2007, for unicode / non unicode messages and any other combinations. It was working in all cases.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-4799157496130142311?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/4799157496130142311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/08/metadata-extraction-from-ms-outlook.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/4799157496130142311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/4799157496130142311'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/08/metadata-extraction-from-ms-outlook.html' title='Metadata extraction from MS Outlook messages'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-8871105169084901551</id><published>2010-07-27T08:32:00.000-07:00</published><updated>2010-07-27T08:43:43.053-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Apache POI'/><title type='text'>Metadata extraction from MS Office documents with Apache POI</title><content type='html'>Microsoft Office documents have several metadata or properties like "Title", "Author", "Comments", "Keywords", "CreateDateTime", "LastSaveDateTime", etc. &lt;a href="http://poi.apache.org/"&gt;Apache POI HPSF&lt;/a&gt;, Java API for Microsoft documents, is a neat library to extract such properties from Word, Excel or PowerPoint documents. It can be useful if user upload MS Office files and would like to show / edit metadata before uploaded files are stored in a content repository or somewhere else. Let's write an Java class named &lt;span style="color: orange;"&gt;MsOfficeExtractor&lt;/span&gt;.&lt;br /&gt;&lt;pre class="brush:java"&gt;import java.io.ByteArrayInputStream;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.InputStream;&lt;br /&gt;import java.lang.reflect.Method;&lt;br /&gt;import java.util.Arrays;&lt;br /&gt;import java.util.Collections;&lt;br /&gt;import java.util.HashMap;&lt;br /&gt;import java.util.Map;&lt;br /&gt;import org.apache.poi.hpsf.PropertySetFactory;&lt;br /&gt;import org.apache.poi.hpsf.SummaryInformation;&lt;br /&gt;import org.apache.poi.poifs.eventfilesystem.POIFSReader;&lt;br /&gt;import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;&lt;br /&gt;import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;&lt;br /&gt;&lt;br /&gt;public class MsOfficeExtractor&lt;br /&gt;{&lt;br /&gt; private String[] properties;&lt;br /&gt; private Map&amp;lt;String, Method&amp;gt; methodMap;&lt;br /&gt;&lt;br /&gt; public MsOfficeExtractor(final String[] properties)&lt;br /&gt; {&lt;br /&gt;  this.properties = (properties == null ? new String[] {} : properties);&lt;br /&gt;  methodMap = new HashMap&amp;lt;String, Method&amp;gt;();&lt;br /&gt;  try {&lt;br /&gt;   for (int i = 0; i &amp;lt; properties.length; i++) {&lt;br /&gt;    methodMap.put(properties[i], SummaryInformation.class.getMethod("get" + properties[i], (Class[]) null));&lt;br /&gt;   }&lt;br /&gt;  } catch (SecurityException e) {&lt;br /&gt;   // error handling&lt;br /&gt;  } catch (NoSuchMethodException e) {&lt;br /&gt;   // error handling&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public Map&amp;lt;String, Object&amp;gt; parseMetaData(final byte[] data)&lt;br /&gt; {&lt;br /&gt;  if (properties.length == 0) {&lt;br /&gt;   return Collections.EMPTY_MAP;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  InputStream in = null;&lt;br /&gt;  try {&lt;br /&gt;   in = new ByteArrayInputStream(data);&lt;br /&gt;   POIFSReader poifsReader = new POIFSReader();&lt;br /&gt;   MetaDataListener metaDataListener = new MetaDataListener();&lt;br /&gt;   poifsReader.registerListener(metaDataListener, "\005SummaryInformation");&lt;br /&gt;   poifsReader.read(in);&lt;br /&gt;&lt;br /&gt;   return metaDataListener.metaData;&lt;br /&gt;  } catch (final IOException e) {&lt;br /&gt;   // error handling&lt;br /&gt;  } catch (final RuntimeException e) {&lt;br /&gt;   // error handling&lt;br /&gt;  } finally {&lt;br /&gt;   if (in != null) {&lt;br /&gt;    try {&lt;br /&gt;     in.close();&lt;br /&gt;    } catch (IOException e) {&lt;br /&gt;     // nothing to do&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The constructor expects property names of the properties we want to extract. All valid names are defined in &lt;span style="color: orange;"&gt;org.apache.poi.hpsf.SummaryInformation&lt;/span&gt;. The map &lt;span style="color: orange;"&gt;methodMap &lt;/span&gt;defines a mapping between a property to be extracted and a method to be called in the listener explained below. The core method is &lt;span style="color: orange;"&gt;parseMetaData &lt;/span&gt;which expects a byte array of given MS Office file. We need now a listener class &lt;span style="color: orange;"&gt;MetaDataListener &lt;/span&gt;which is called while parsing.&lt;br /&gt;&lt;pre class="brush:java"&gt;public class MetaDataListener implements POIFSReaderListener&lt;br /&gt;{&lt;br /&gt; public final Map&amp;lt;String, Object&amp;gt; metaData;&lt;br /&gt;&lt;br /&gt; public MetaDataListener()&lt;br /&gt; {&lt;br /&gt;  metaData = new HashMap&amp;lt;String, Object&amp;gt;();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void processPOIFSReaderEvent(final POIFSReaderEvent event)&lt;br /&gt; {&lt;br /&gt;  try {&lt;br /&gt;   final SummaryInformation summaryInformation = (SummaryInformation) PropertySetFactory.create(event.getStream());&lt;br /&gt;&lt;br /&gt;   for (int i = 0; i &amp;lt; properties.length; i++) {&lt;br /&gt;    Method method = (Method) methodMap.get(properties[i]);&lt;br /&gt;    Object propertyValue = method.invoke(summaryInformation, (Object[]) (Object[]) null);&lt;br /&gt;&lt;br /&gt;    metaData.put(properties[i], propertyValue);&lt;br /&gt;   }&lt;br /&gt;  } catch (final Exception e) {&lt;br /&gt;   // error handling&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The goal of this listener is to build a map with extracted values to the given properties (which values we want to extract). The using is simple:&lt;br /&gt;&lt;pre class="brush:java"&gt;// initialize extractor&lt;br /&gt;String[] poiProperties = new String[] {"Comments", "CreateDateTime", "LastSaveDateTime"};&lt;br /&gt;MsOfficeExtractor msOfficeExtractor = new MsOfficeExtractor(poiProperties);&lt;br /&gt;&lt;br /&gt;// get byte array of any MS office document&lt;br /&gt;byte[] data = ...&lt;br /&gt;&lt;br /&gt;// extract metadata&lt;br /&gt;Map&amp;lt;String, Object&amp;gt; metadata = msOfficeExtractor.parseMetaData(data);&lt;br /&gt;&lt;/pre&gt;In the next post I will show how to extract metadata from MS Outlook msg files. Apache POI-HSMF, Java API to access MS Outlook msg files, has limits and is not flexible enough. I will present my own powerful solution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-8871105169084901551?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/8871105169084901551/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/07/metadata-extraction-from-ms-office.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/8871105169084901551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/8871105169084901551'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/07/metadata-extraction-from-ms-office.html' title='Metadata extraction from MS Office documents with Apache POI'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-8169654574858163010</id><published>2010-07-21T05:31:00.000-07:00</published><updated>2010-07-23T03:26:27.278-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><title type='text'>Encode / decode parameters for GET request</title><content type='html'>As is well-known GET request parameters (query string) must be encoded on client-side and decoded on server-side. Normally an application server is responsible for decoding URL parameters. But in the real world I already had a case where parameters were not decoded (maybe some settings were wrong). Well. The client-side solution which I wrote for my web apps is to pass request parameters through this function&lt;br /&gt;&lt;pre class="brush:js"&gt;// Replaces all special characters in the passed string.&lt;br /&gt;function encodeString(thestring)&lt;br /&gt;{&lt;br /&gt;    var encodedValue;&lt;br /&gt;    if(window.encodeURIComponent) {&lt;br /&gt;        encodedValue = encodeURIComponent(thestring);&lt;br /&gt;    } else {&lt;br /&gt;        encodedValue = escape(thestring);&lt;br /&gt;        encodedValue = encodedValue.replace(new RegExp('\\+', 'g'), '%2B');&lt;br /&gt;    }&lt;br /&gt;    return encodedValue;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The Java based server-side solution (if needed) is easy.&lt;br /&gt;&lt;pre class="brush:js"&gt;String encoding = request.getCharacterEncoding();&lt;br /&gt;if (encoding == null) {&lt;br /&gt;    encoding = &amp;quot;UTF-8&amp;quot;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;try {&lt;br /&gt;    String decodedParameter = java.net.URLDecoder.decode(originalParameter, encoding);&lt;br /&gt;    ...&lt;br /&gt;} catch (UnsupportedEncodingException e) {&lt;br /&gt;    // do something&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-8169654574858163010?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/8169654574858163010/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/07/encode-decode-parameters-for-get.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/8169654574858163010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/8169654574858163010'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/07/encode-decode-parameters-for-get.html' title='Encode / decode parameters for GET request'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-1393128622314396895</id><published>2010-07-21T04:10:00.000-07:00</published><updated>2010-07-21T04:10:01.123-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><title type='text'>What element mouse comes from or goes to</title><content type='html'>Sometimes we want to know where the mouse comes from or goes to in case of mouseover / mouseout event. Assume, we have assigned to any HTML element a mouseout listener &lt;span style="color: orange;"&gt;mouseOut&lt;/span&gt;. We can easy acquire the source (from element) and target (to element) by fired event.&lt;br /&gt;&lt;pre class="brush:js"&gt;function mouseOut(evt)&lt;br /&gt;{&lt;br /&gt;    evt = (evt) ? evt : ((window.event) ? window.event : "");&lt;br /&gt;    var fromElement = (evt.target) ? evt.target : evt.srcElement;&lt;br /&gt;    var toElement = (evt.relatedTarget) ? evt.relatedTarget : evt.toElement;&lt;br /&gt;    &lt;br /&gt;    // do something with fromElement / toElement&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Easy. Is not?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-1393128622314396895?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/1393128622314396895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/07/what-element-mouse-comes-from-or-goes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1393128622314396895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/1393128622314396895'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/07/what-element-mouse-comes-from-or-goes.html' title='What element mouse comes from or goes to'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-5924015937858883813</id><published>2010-07-21T03:40:00.000-07:00</published><updated>2010-07-21T03:50:07.267-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><title type='text'>A cross-browser solution to get iframe body element</title><content type='html'>An often task while web development is the working with iframe. If we have iframe's body object &lt;span style="color: orange;"&gt;bodyIframe&lt;/span&gt; we can use quite normally JavaScript means to do for instance its content empty&lt;br /&gt;&lt;pre class="brush:javascript"&gt;...&lt;br /&gt;bodyIframe.innerHTML = "";&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;or to get any HTML form like&lt;br /&gt;&lt;pre class="brush:javascript"&gt;...&lt;br /&gt;var form = bodyIframe.getElementsByTagName("form")[0];&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;or something else. Unfortunately there isn't an uniform access to iframe's body object. It's dependent on browser. I have found out an universal way to get this element by iframe Id (&lt;span style="color: orange;"&gt;&amp;lt;iframe id="..." .../&amp;gt;&lt;/span&gt;). The appropriate JS function looks as follows&lt;br /&gt;&lt;pre class="brush:javascript"&gt;function getIframeBody(iframeId)&lt;br /&gt;{&lt;br /&gt;   var obj = document.getElementById(iframeId);&lt;br /&gt;   if (obj == null) {&lt;br /&gt;      return null;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   var bodyIframe = null;&lt;br /&gt;   if (obj.contentWindow &amp;amp;&amp;amp; obj.contentWindow.document.body) {&lt;br /&gt;      bodyIframe = obj.contentWindow.document.body;&lt;br /&gt;   } else if (obj.document &amp;amp;&amp;amp; obj.document.body) {&lt;br /&gt;      bodyIframe = obj.document.body;&lt;br /&gt;   } else if (obj.contentDocument &amp;amp;&amp;amp; obj.contentDocument.body) {&lt;br /&gt;      bodyIframe = obj.contentDocument.body;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   return bodyIframe;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8492059842142356488-5924015937858883813?l=ovaraksin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ovaraksin.blogspot.com/feeds/5924015937858883813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ovaraksin.blogspot.com/2010/07/cross-browser-solution-to-get-iframe.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/5924015937858883813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8492059842142356488/posts/default/5924015937858883813'/><link rel='alternate' type='text/html' href='http://ovaraksin.blogspot.com/2010/07/cross-browser-solution-to-get-iframe.html' title='A cross-browser solution to get iframe body element'/><author><name>Oleg Varaksin</name><uri>http://www.blogger.com/profile/13872270134068047346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://2.bp.blogspot.com/_r2bVl8CocQo/TCRaFvTt34I/AAAAAAAAACc/a5KMAYbdzpc/S220/olegcv.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8492059842142356488.post-3666744453817109449</id><published>2010-07-20T13:52:00.000-07:00</published><updated>2010-07-20T14:42:34.845-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jackrabbit'/><category scheme='http://www.blogger.com/atom/ns#' term='JCR'/><title type='text'>How to access Jackrabbit content repository via JNDI?</title><content type='html'>In &lt;a href="http://ovaraksin.blogspot.com/2010/07/setting-up-shared-jackrabbit-content.html"&gt;this post&lt;/a&gt; I described how an Jackrabbit content repository can be set up. I will show now how it can be accessed via JNDI. I dont' want to write an JNDI lookup although it's not difficult. I would like to use &lt;a href="http://code.google.com/p/google-guice/"&gt;Google Guice&lt;/a&gt;, a dependency injection framework. At first we need a Guice configuration module.&lt;br /&gt;&lt;pre class="brush:java"&gt;public class DefaultConfigurationGuiceModule extends AbstractModule&lt;br /&gt;{&lt;br /&gt;    protected void configure()&lt;br /&gt;    {&lt;br /&gt;        bind(String.class).annotatedWith(Names.named("repository name")).toInstance("jcr/repository");&lt;br /&gt;&lt;br /&gt;        // bind naming context to the default InitialContext&lt;br /&gt;        bind(Context.class).to(InitialContext.class);&lt;br /&gt;&lt;br /&gt;        // bind to the repository from JNDI&lt;br /&gt;        bind(Repository.class).toProvider(JndiIntegration.fromJndi(Repository.class, "jcr/repository"));&lt;br /&gt;&lt;br /&gt;        // bind to the factory class for the creation of repository accessor&lt;br /&gt;        // see http://code.google.com/docreader/#p=google-guice&amp;amp;s=google-guice&amp;amp;t=AssistedInject&lt;br /&gt;        bind(RepositoryAccessorFactory.class).toProvider(FactoryProvider.newFactory(RepositoryAccessorFactory.class,&lt;br /&gt;                                             JackrabbitRepositoryAccessor.class)).in(Singleton.class);&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Guice has a helpful class &lt;span style="color: orange;"&gt;JndiIntegration &lt;/span&gt;to create a provider which looks up objects in JNDI using the given name. Furthermore I use Guice's &lt;span style="color: orange;"&gt;AssistedInject &lt;/span&gt;and define a factory interface to create an instance for repository access (&lt;span style="color: orange;"&gt;JackrabbitRepositoryAccessor&lt;/span&gt;). The real factory will be created by &lt;span style="color: orange;"&gt;AssistedInject&lt;/span&gt;.&lt;br /&gt;&lt;pre class="brush:java"&gt;public interface RepositoryAccessorFactory&lt;br /&gt;{&lt;br /&gt;    /**&lt;br /&gt;     * Greates an instance of {@link RepositoryAccessor}. Sets an input stream of XML file which describes custom node&lt;br /&gt;     * types and appropriated custom namespace mapping. Custom node types and namespace will be registered one-time if&lt;br /&gt;     * the JCR session is requested and they were not registered yet.&lt;br /&gt;     *&lt;br /&gt;     * @param  nodeTypeConfigs configurations of custom node types to be registered&lt;br /&gt;     * @return RepositoryAccessor the instance of {@link RepositoryAccessor}&lt;br /&gt;     */&lt;br /&gt;    RepositoryAccessor create(@Assisted final NodeTypeConfig[] nodeTypeConfigs);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The class &lt;span style="color: orange;"&gt;
