tag:blogger.com,1999:blog-26189840732084824112024-03-13T11:49:14.035-07:00Software DevelopmentThomas Andraschkohttp://www.blogger.com/profile/17675421796799997447noreply@blogger.comBlogger16125tag:blogger.com,1999:blog-2618984073208482411.post-7183710859897673872020-06-24T01:53:00.001-07:002020-06-24T01:53:49.487-07:00How to use Microprofile with tomee-embedded-maven-pluginHere is a sample POM how to use Microprofile with tomee-embedded-maven-plugin 8.x:
<br />
<pre class="brush:xml;">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.tomee</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0-3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.microprofile</groupId>
<artifactId>microprofile</artifactId>
<version>2.0</version>
<type>pom</type>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>javax.json</groupId>
<artifactId>javax.json.bind-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-api</artifactId>
<version>2.3.6</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>test</finalName>
<plugins>
<plugin>
<groupId>org.apache.tomee.maven</groupId>
<artifactId>tomee-embedded-maven-plugin</artifactId>
<version>8.0.2</version>
<configuration>
<context>ROOT</context>
<containerProperties>
<tomee.mp.scan>true</tomee.mp.scan>
</containerProperties>
</configuration>
<dependencies>
<dependency>
<groupId>org.apache.tomee</groupId>
<artifactId>mp-common</artifactId>
<version>8.0.2</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
</project>
</pre>
Thomas Andraschkohttp://www.blogger.com/profile/17675421796799997447noreply@blogger.com34tag:blogger.com,1999:blog-2618984073208482411.post-72149349501866634452019-03-12T09:16:00.002-07:002019-03-12T09:17:41.224-07:00JSF benchmark 2019See: <a href="https://github.com/tandraschko/jsfbench">https://github.com/tandraschko/jsfbench</a>Thomas Andraschkohttp://www.blogger.com/profile/17675421796799997447noreply@blogger.com5tag:blogger.com,1999:blog-2618984073208482411.post-39361585092478842422019-03-05T07:48:00.002-08:002020-08-12T08:08:18.784-07:00Way to MyFaces 2.3-nextI (and other commiters) spend many hours to prepare the MyFaces codebase for the upcoming version 2.3-next during the last months, which will be MyFaces 4.0 in the future.<br />JSF (or Jakarta Faces) 3.0 will be 1:1 the same as JSF 2.3, just with the jakarta.* package names.<br />
<br />
In 2.3-next, we did BIG BIG cleanup of our codebase and build.<br />Wee also removed the old JSF EL (javax.faces.el.*) and @ManagedBean (javax.faces.bean.*) implementations.<br />What does this mean? The API (javax.faces.el.*) and (javax.faces.bean.*) is still there but the implementation of it has been removed partially. @ManagedBean's are now registered as CDI beans, which means that a CDI runtime is a required dependency now.<br /><br />
The biggest clenaup was that we merged back the "shared" and "shared-public" modules to myfaces-impl, as the shared modules are no longer used by other active projects under the MyFaces umbrella.<br />
We also introduced some real integration tests with Arquillian, to test parts of the container integration and AJAX client side. This makes around 1600 unittests!<br />
<br />
OK.... Lets compare some numbers!<br />
<br />
JAR size:<br />
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
.tg .tg-baqh{text-align:center;vertical-align:top}
.tg .tg-amwm{font-weight:bold;text-align:center;vertical-align:top}
</style>
<br />
<table class="tg">
<tbody>
<tr>
<th class="tg-baqh"><br /></th>
<th class="tg-amwm">Mojarra 2.3</th>
<th class="tg-amwm">MyFaces 2.3</th>
<th class="tg-amwm">MyFaces 2.3-next</th>
</tr>
<tr>
<td class="tg-amwm"><br />
API</td>
<td class="tg-baqh"></td>
<td class="tg-baqh">1318 kb</td>
<td class="tg-baqh">1043 kb</td>
</tr>
<tr>
<td class="tg-amwm">IMPL</td>
<td class="tg-baqh">3495 kb (combined) </td>
<td class="tg-baqh">2712 kb</td>
<td class="tg-baqh">2384 kb</td>
</tr>
<tr>
<td class="tg-amwm"><br />
Dependencies</td>
<td class="tg-baqh"></td>
<td class="tg-baqh">241 kb (beanutils)<br />
141 kb (digester)</td>
<td class="tg-baqh"></td>
</tr>
<tr>
<td class="tg-amwm">TOTAL</td>
<td class="tg-baqh">3495 kb</td>
<td class="tg-baqh">4412 kb</td>
<td class="tg-baqh">3427 kb</td>
</tr>
</tbody></table>
<br />
<br />
<br />
Performance:<br />
NOTE: this is not a full benchmark, it's only a single case to demonstrate the difference between MyFaces 2.3 and MyFaces 2.3-next, which was inspired from: <a href="https://www.oio.de/public/java/studie-jsf-mojarra-myfaces-performance-vergleich.htm">https://www.oio.de/public/java/studie-jsf-mojarra-myfaces-performance-vergleich.htm</a><br />
We have to rerun <a href="https://github.com/lu4242/performance-comparison-java-web-frameworks">https://github.com/lu4242/performance-comparison-java-web-frameworks</a> later for a real comparison between MyFaces and Mojarra.<br />
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:black;}
.tg .tg-baqh{text-align:center;vertical-align:top}
.tg .tg-amwm{font-weight:bold;text-align:center;vertical-align:top}
</style>
<br />
<table class="tg">
<tbody>
<tr>
<th class="tg-baqh"><br /></th>
<th class="tg-amwm">Mojarra 2.3</th>
<th class="tg-amwm">MyFaces 2.3</th>
<th class="tg-amwm">MyFaces 2.3-next</th>
</tr>
<tr>
<td class="tg-amwm">GET input.xhtml</td>
<td class="tg-baqh">Average: 67 ms</td>
<td class="tg-baqh">Average: 62 ms</td>
<td class="tg-baqh">Average: 43 ms</td>
</tr>
<tr>
<td class="tg-amwm">POST input.xhtml</td>
<td class="tg-baqh">Average: 115 ms</td>
<td class="tg-baqh">Average: 122 ms</td>
<td class="tg-baqh">Average: 108 ms</td>
</tr>
<tr>
<td class="tg-amwm">GET detail.xhtml</td>
<td class="tg-baqh">Average: 119 ms</td>
<td class="tg-baqh">Average: 124 ms</td>
<td class="tg-baqh">Average: 103 ms</td>
</tr>
<tr>
<td class="tg-amwm">POST detail.xhtml</td>
<td class="tg-baqh">Average: 70 ms</td>
<td class="tg-baqh">Average: 54 ms</td>
<td class="tg-baqh">Average: 43 ms</td>
</tr>
<tr>
<td class="tg-amwm">TOTAL</td>
<td class="tg-baqh">Average: 92 ms<br />
Throughput: 198.7/s</td>
<td class="tg-baqh">Average: 91 ms<br />
Throughput: 209.8/sec</td>
<td class="tg-baqh">Average: 74 ms<br />
Throughput: 264.2/sec </td>
</tr>
</tbody></table>
<br />
This means that MyFaces 3.0 is up to ~15% faster as the already very fast MyFaces 2.3 in this case.<br />
We also did some memory finetuning - i just don't have any numbers right now.Thomas Andraschkohttp://www.blogger.com/profile/17675421796799997447noreply@blogger.com7tag:blogger.com,1999:blog-2618984073208482411.post-17299675440763032412019-02-05T02:35:00.001-08:002019-02-05T02:35:25.420-08:00Maven: use lombok combined with OpenJPA metadata generationHere is a example how to use lombok combined with OpenJPA metadata generation inside the maven-compiler-plugin:
<pre class="brush:xml;">
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
</dependency>
<!-- needs to be defined here for the annotation processor -->
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa</artifactId>
<version>3.0.0</version>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<annotationProcessors>
<annotationProcessor>lombok.launch.AnnotationProcessorHider$AnnotationProcessor</annotationProcessor>
<annotationProcessor>org.apache.openjpa.persistence.meta.AnnotationProcessor6</annotationProcessor>
</annotationProcessors>
<compilerArgs>
<arg>-Aopenjpa.metamodel=true</arg>
<arg>-Aopenjpa.source=7</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</pre>Thomas Andraschkohttp://www.blogger.com/profile/17675421796799997447noreply@blogger.com16tag:blogger.com,1999:blog-2618984073208482411.post-16137514775765510902017-11-07T08:10:00.000-08:002019-01-08T13:20:13.640-08:00Increase your JSF application performance - Version 2017As my last posts are already 5 years old, i think it's time for a new one :D<br />
<br />
<h2>
Environment: </h2>
<br />
If you would like to use a JavaEE application server, i would go with TomEE.<br />
It's the fastest and smallest application server available and already comes with Apache MyFaces as JSF implementation and Apache OpenWebBeans as CDI implementation.<br />
<br />
There are already really good benchmarks available why we should choose MyFaces over Mojarra and OpenWebBeans over Weld:<br />
<br />
<a href="http://content.jsfcentral.com/c/journal_articles/view_article_content?groupId=35702&articleId=66621&version=2.3#.WfoSL3Bryhc">Understanding JSF 2.0 Performance – Part 1</a><br />
<a href="http://content.jsfcentral.com/c/journal/view_article_content?cmd=view&groupId=35702&articleId=69713&version=1.5#.WfoSMHBryhc">Understanding JSF 2.0 Performance – Part 2</a><br />
<a href="http://content.jsfcentral.com/c/journal/view_article_content?cmd=view&groupId=35702&articleId=73398&version=1.8#.WfoSMHBryhc">Understanding JSF 2.0 Performance – Part 3</a><br />
<a href="https://github.com/struberg/cdi-performance">CDI Performance</a><br />
<br />
So if you just use a plain servlet container like Tomcat or Jetty, i would also use MyFaces and OpenWebBeans. <br />
<br />
In the past it was also a good performance boost if you use JUEL over Tomcat's EL implementation - sadly JUEL doesn't implement EL 3.0.<br />
<br />
<ul></ul>
<h2>
Configuration: </h2>
<br />
<ul>
<li>Common settings:</li>
<pre class="brush:xml;"><context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Production</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
<param-value>-1</param-value>
</context-param>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param></pre>
<li>Enable ViewPooling: <a href="http://lu4242.blogspot.de/2013/12/view-pooling-in-jsf-22-using-apache.html">http://lu4242.blogspot.de/2013/12/view-pooling-in-jsf-22-using-apache.html</a> </li>
NOTE: You must also set:<pre class="brush:xml;"><context-param>
<param-name>org.apache.myfaces.CACHE_EL_EXPRESSIONS<span style="color: #e8bf6a;"></span></param-name>
<param-value>alwaysRecompile</param-value>
</context-param></pre>
<li>Enable WhiteSpace compression: <a href="http://lu4242.blogspot.de/2012/12/html-white-space-compression-for-jsf.html">http://lu4242.blogspot.de/2012/12/html-white-space-compression-for-jsf.html</a></li>
<li>Disable JSP support in MyFaces - this increases the startup performance and EL resolution:</li>
<pre class="brush:xml;"><context-param>
<param-name>org.apache.myfaces.SUPPORT_JSP_AND_FACES_EL</param-name>
<param-value>false</param-value>
</context-param>
<!--
NOTE: the ExpressionFactory might differ e.g. on Glassfish or Wildfly.
This parameter is optional since MyFaces 2.3.3.
-->
<context-param>
<param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
<param-value>org.apache.el.ExpressionFactoryImpl</param-value>
</context-param> </pre>
<li>Disable ManagedBeans support (since 2.3): <br /><pre class="brush:xml;"><context-param>
<param-name>org.apache.myfaces.SUPPORT_MANAGED_BEANS</param-name>
<param-value>false</param-value>
</context-param></pre>
</li>
<li>Reduce saved view states: <br /><pre class="brush:xml;"><context-param>
<param-name>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</param-name>
<param-value>15</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION</param-name>
<param-value>3</param-value>
</context-param> </pre>
</li>
<li>Disable ViewState compression (better performance but more memory usage):<pre class="brush:xml;"><context-param>
<param-name>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</param-name>
<param-value>false</param-value>
</context-param></pre>
</li>
<li>Enable partial submit in PrimeFaces - this reduces the network traffic:<pre class="brush:xml;"><context-param>
<param-name>primefaces.SUBMIT</param-name>
<param-value>partial</param-value>
</context-param></pre>
</li>
<li>Move above the fold scripts to the bottom (end of body). This is a huge improvement of the visible rendering and removes flickering between navigations (since 6.2):<br /><pre class="brush:xml;"><context-param>
<param-name>primefaces.MOVE_SCRIPTS_TO_BOTTOM</param-name>
<param-value>true</param-value>
</context-param></pre>
</li>
<li>Other params to increase performance:</li>
<pre class="brush:xml;"><context-param>
<param-name>org.apache.myfaces.CHECK_ID_PRODUCTION_MODE</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.EARLY_FLUSH_ENABLED</param-name>
<param-value>true</param-value>
</context-param></pre>
<li>Use a custom ServletFilter to set the correct expires/cache headers of your resources (images, stylesheets, javascripts). This is only required if you don't use the JSF resource handling for every resource. The JSF impl should already do it correctly for all JSF managed resources.</li>
<li>Compress and optimize your Javascripts in your build process. If you
use maven, try primefaces-extensions' closure compiler maven plugin.</li>
<li>Enable GZIP in your webserver! If it's not supported by your webserver/container, you can still add the GzipResponseFilter from OmniFaces: http://showcase.omnifaces.org/filters/GzipResponseFilter</li>
</ul>
<br />
<h2>
Patterns: </h2>
<br />
<ul>
<li>Correctly define update/render and process/execute! Often this is a huge improvement as many times the whole form is updated instead only a small part. But i also prefer maintainability over performance here.</li>
<li>If you don't use ViewScoped beans, it's a good but small improvement to mark the view as stateless via transient=true.</li>
<li>Try using HTML over JSF tags. </li>
<ul>
<li>Especially avoid using h:outputText if you don't need the escaping. Just use EL expressions inside your xhtml template.</li>
<li>The same applies for some other components like p:outputPanel. Just use a plain div. If you need to make it updateable, you can still use "passtrough elements" (<div jsf:id="...">...</div>)</li>
</ul>
<li>Never put logic in getters because they can be called multiple times - especially for the rendered attribute!</li>
<li>Avoid logic (like inline if-statements) in EL expression! It's better to move those logic into the bean. It's faster and often easier to read and maintain.</li>
<li>Prefer AJAX over a full postback!</li>
<li>If you have many p:outputLabel's on the page and you know that the input field is required or not, it's a good performance improvemet to set the input to required=true or the outputLabel to indicateRequired=true|false. The default value for indicateRequired since 6.2 is auto, which tries to lookup BeanValidation constrains to check if @NotNull|@NotEmpty|@NotBlank are defined.</li>
<li>Cache data, which is required multiple times in the same view, in @RequestScoped beans.</li>
<li>Avoid missusing @SessionScoped, @ViewScoped and other long living scopes if not really required. </li>
<li>Try to put only small amount of data in such long living beans. Sometimes a small flag or id of an entity is enough information. Often people put many entities in such long living beans. One of my patterns is to split beans into *Controllers (@RequestScoped) and *StateHolders (@ViewScoped, @ViewAccessScoped). *StateHolders are just data containers.</li>
</ul>
Thomas Andraschkohttp://www.blogger.com/profile/17675421796799997447noreply@blogger.com14tag:blogger.com,1999:blog-2618984073208482411.post-29140602826301141252016-01-25T01:06:00.000-08:002016-01-25T01:06:21.437-08:00Enable failover with OpenWebBeans (>= 1.5.1)Since OWB 1.5.1 you don't need any configuration or FailOverFilter anymore as the beans are directly stored in the HttpSession :)Thomas Andraschkohttp://www.blogger.com/profile/17675421796799997447noreply@blogger.com1tag:blogger.com,1999:blog-2618984073208482411.post-70287098776389839012013-09-21T10:11:00.000-07:002013-09-21T17:57:54.398-07:00Session replication / clustering / failover with Tomcat (Part 1 - Overview)This is my first post of a series about Tomcat and clustering.<br />
In this post i will explain some different replication mechanism.<br />
<br />
<br />
NOTE: A common drawback of replication, like it's defined in the specs, is that only HttpSession#setAttribute(...) triggers replication.<br />
This means that if you store a container object in the session and if you change a variable inside the object, you must HttpSession#setAttribute(...) again to replicate the modified object again.<br />
Many frameworks implements a simple workaround for it - i will write about it another post.<br />
<br />
<br />
<h3>
All to all replication / DeltaManager </h3>
<br />
With this mode, Tomcat just replicates the session to all registered nodes.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-lA9UVwkEWV0/Uj3P_R1a-NI/AAAAAAAAADI/wyOjiE0nbLg/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="167" src="http://4.bp.blogspot.com/-lA9UVwkEWV0/Uj3P_R1a-NI/AAAAAAAAADI/wyOjiE0nbLg/s320/1.png" width="320" /></a></div>
<br />
Pro:<br />
<ul>
<li>No single point of failure at software level</li>
<li>Every node holds all sessions</li>
<li>In theory, all other nodes can be turned off</li>
<li>No extra software is needed</li>
<li>Synchronous or Asynchronous replication</li>
<li>Open Source</li>
<li>Enterprise-Support available</li>
</ul>
Contra:<br />
<ul>
<li>High memory usage and network traffic because all nodes holds all sessions</li>
<li>Objects which are stored in the session must be triggered manually to replicate again if a property has been changed</li>
<li>Slower session serialization</li>
</ul>
<br />
<br />
<br />
<h3>
Primary/Secondary Replication (Buddy Replication) / BackupManager</h3>
<br />
The sessions will be replicated to the next neighbor. If one Tomcat is not available anymore, the neighbor still holds the sessions.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-KL2uXjBbM2s/Uj3QGtwyBEI/AAAAAAAAADM/xbgsjG0uhUI/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="166" src="http://2.bp.blogspot.com/-KL2uXjBbM2s/Uj3QGtwyBEI/AAAAAAAAADM/xbgsjG0uhUI/s320/2.png" width="320" /></a></div>
<br />
Pro:<br />
<ul>
<li>No single point of failure at software level</li>
<li>Lower memory usage and network traffic because the session is not stored on all nodes</li>
<li>No extra software is needed</li>
<li>Synchronous or Asynchronous replication</li>
<li>Open Source</li>
<li>Enterprise-Support available </li>
</ul>
Contra:<br />
<ul>
<li>Not quite as battle tested as the All-to-all replication (see Tomcat documentation)</li>
<li>Objects which are stored in the session must be triggered manually to
replicate again if a property has been change </li>
<li>Slower session serialization </li>
</ul>
<br />
<br />
<br />
<h3>
Memcached-session-manager</h3>
<br />
Each Tomcat replicates all sessions to N (multiple) Memcached nodes.<br />
If a session is not available on the local Tomcat, the memcached-session-manager tries to lookup the session from the Memcached nodes.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-tytzlno9E8E/Uj3QNnlWYPI/AAAAAAAAADU/-zI0mfxL2ig/s1600/3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-tytzlno9E8E/Uj3QNnlWYPI/AAAAAAAAADU/-zI0mfxL2ig/s1600/3.png" /></a></div>
<br />
Pro:<br />
<ul>
<li>No single point of failure at software level</li>
<li>More scalability</li>
<li>Session will be replicated to N “Memcached” nodes – The sessions are still available if all webservers are down </li>
<li>Automatically handles “Memcached” nodes failover</li>
<li>Sticky mode: Lower memory usage because every node holds only the current used sessions</li>
<li>Non-Sticky mode: Lowest memory usage because Tomcat does not hold the sessions anymore. Session will be received from memcached for each request</li>
<li>MSM will automatically trigger replication if a property in a session stored object has been changed</li>
<li>Faster session serialization – Changeable mechanism</li>
<li>Synchronous or Asynchronous replication</li>
<li>Open Source</li>
<li>Enterprise-Support available for Tomcat</li>
</ul>
Contra:<br />
<ul>
<li>Extra software needed (“Memcached” plugin and nodes)</li>
<li>Cannot switch to another Java Webserver which does not automatically check changed values in the session - but only if the used framework has no implemented workaround </li>
<li>AFAIK no Enterprise-Support available for the Memcached plugin but Martin Grotzke is very active on the mailing list</li>
</ul>
<br />Thomas Andraschkohttp://www.blogger.com/profile/17675421796799997447noreply@blogger.com90tag:blogger.com,1999:blog-2618984073208482411.post-72932395421563519162013-09-19T05:31:00.001-07:002013-09-19T05:37:30.222-07:00Enable failover with OpenWebBeans (> 1.2.0) In my first post i already explained how it's possible to enable failover (aka clustering) with OpenWebBeans > 1.1.3: <a href="http://tandraschko.blogspot.de/2012/08/test.html">Enable failover with OpenWebBeans (> 1.1.3) </a><br />
<br />
Because we moved the clustering logic to own module, we must include this module since OWB 1.2.0:<br />
<pre class="brush:xml;"><dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-clustering</artifactId>
</dependency></pre>
<br />
You still need the org.apache.webbeans.web.failover.FailOverFilter but if you include this module, you must NOT add a custom openwebbeans.properties anymore.
It will be registered automatically.
Thomas Andraschkohttp://www.blogger.com/profile/17675421796799997447noreply@blogger.com4tag:blogger.com,1999:blog-2618984073208482411.post-57009957065845955872013-09-18T05:54:00.001-07:002013-09-19T13:24:45.016-07:00PrimeFaces Extensions 1.0This week, Oleg released a RC of PrimeFaces Extensions as you can read here: <a href="http://ovaraksin.blogspot.de/2013/09/primefaces-extensions-100rc1-released.html">PrimeFaces Extensions 1.0.0.RC1 released</a><br />
<br />
To be honest, i had not much time to improve anything in PrimeFaces Extensions.
<br />
I'm PrimeFaces committer since January 2013 and it was more fun to implement new features, working on complex stuff together with Çağatay or improve performance directly in PrimeFaces Core.
<br />
I also will blog about some of this features the next weeks.
<br />
<br />
The biggest of my changes in PrimeFaces Extensions 1.0 are the PrimeFaces 4.0 compatibility and a new CKEditor version (4.2.1 now).
<br />
<br />
It's not sooo easy to marry CKEditor and the resource handling of JSF. I had to adjust some of there code and created some issues on their side.<br />
If they will improve it and fix those issues, updating CKEditor will much easier in the future.<br />
CKEditor removed and introduced new skins. Supported skins are "kama" and "moono" now.
<br />
<br />
We also added support for "my" new <a href="http://blog.primefaces.org/?p=2740">Search Expression Framework</a> of PrimeFaces 4.0 in all our components.
<br />
<br />
<span class="short_text" id="result_box" lang="en"><span class="hps">We</span> <span class="hps">were also able to</span> <span class="hps">clean up</span> <span class="hps">some code </span></span>because i could move some features or API changes directly to PrimeFaces Core.<br />
<br />
Stay tuned for the final release!Thomas Andraschkohttp://www.blogger.com/profile/17675421796799997447noreply@blogger.com1tag:blogger.com,1999:blog-2618984073208482411.post-21413363074115302542012-12-14T04:35:00.000-08:002013-02-10T09:34:28.347-08:00Dynamical switching of JSF state saving method By default, it's only possible to configure the state saving method (client or server) globally for all views in your application.<br />
<br />
This is sometimes really annoying as server side performs better but needs more memory.<br />
Also with server side state saving, it's not possible to cache views (if they have actions) because you will get a ViewExpiredException soon.<br />
<br />
So what about using client-side state for some views and using server-side state for all other views?<br />
<br />
Currently this is only possible with MyFaces (since 2.1.9). Mojarra doesn't support this feature.<br />
I created a specifiation improvement ticket (http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1147) and hopefully this will be supported in Mojarra soon.<br />
<br />
So how can we use this feature?<br />
<br />
To switch the state saving method, we just need to overwrite/wrap the following method: <b>StateManager#isSavingStateInClient(FacesContext)</b>.<br />
<br />
In my application i combined this feature with CODI ViewConfig.<br />
<br />
<b>Create a ViewMetaData:</b><br />
<pre class="brush:java;">@Inherited
@ViewMetaData(override = true)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface StateSaving {
Method value();
enum Method {
SERVER,
CLIENT
}
}
</pre>
<br />
<b>Wrap the StateManager:
</b><br />
<pre class="brush:java;">public class ExtensionsStateManager extends StateManagerWrapper {
@Override
public boolean isSavingStateInClient(final FacesContext context) {
boolean isSavingStateInClient;
final StateSaving stateSaving = getStateSavingAnnotationViaCodiViewConfigResolver(context);
if (stateSaving == null) {
isSavingStateInClient = getWrapped().isSavingStateInClient(context);
} else {
isSavingStateInClient = stateSaving.value() == StateSaving.Method.CLIENT;
}
return isSavingStateInClient;
}
}
</pre>
<br />
<b>Configure that JSF should use our StateManager:</b>
<br />
<pre class="brush:xml;"><?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<application>
<state-manager>xxx.xxx.ExtensionsStateManager</state-manager>
</application>
</faces-config>
</pre>
<br />
<b>Usage:</b>
<br />
<pre class="brush:java;">@Page(navigation = NavigationMode.REDIRECT)
public interface Pages extends ViewConfig {
@Page
@StateSaving(Method.SERVER)
class ViewA implements Pages { }
@Page
@StateSaving(Method.CLIENT)
class View implements Pages { }
}</pre>
<br />
<br />
Currently i'm not a member of a library/framework, where i could add this nice feature.<br />
Maybe i will release my own lib for such stuff someday.Thomas Andraschkohttp://www.blogger.com/profile/17675421796799997447noreply@blogger.com5tag:blogger.com,1999:blog-2618984073208482411.post-12261338598420338292012-10-25T03:42:00.000-07:002012-11-06T10:18:21.929-08:00Speedup jetty-maven-plugin startup time<ul>
<li>Create a own profile - this allows more flexibility</li>
<pre class="brush:xml;"><profile>
<id>jetty-run</id>
</profile>
</pre>
<li>Add <b>jetty-maven-plugin </b>to the profile. We also configure the plugin to get all resources from the src directory and only scan the java sources</li>
<pre class="brush:xml;"><plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<webAppSourceDirectory>${basedir}/src/main/webapp</webAppSourceDirectory>
<scanIntervalSeconds>2</scanIntervalSeconds>
<scanTargets>
<scanTarget>src/main/java</scanTarget>
</scanTargets>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</pre>
<li>Skip unit testing via profile property</li>
<pre class="brush:xml;"><properties>
<maven.test.skip>true</maven.test.skip>
</properties>
</pre>
<li>Skip building the WAR file</li>
<pre class="brush:xml;"><plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<executions>
<execution>
<id>default-war</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</pre>
<li>If you optimize and aggregate your javascript or CSS files, skip this too! Compression of this files is on localhost just prevents debugging. We created an own servlet which merges the files on-the-fly. Changes on JS or CSS will be also available after F5 in your browser - that's the nice side effect of the servlet :)</li>
<ul>
<li>Skip optimzation (we use the primefaces-extensions plugin for this)</li>
<pre class="brush:xml;"><plugin>
<groupId>org.primefaces.extensions</groupId>
<artifactId>resources-optimizer-maven-plugin</artifactId>
<executions>
<execution>
<id>optimize</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</pre>
<li>Create a servlet to merge the resources (we also implemented a init-param called includeDirectory to read all source files)</li>
<pre class="brush:java;">@Override
protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException
{
final OutputStream ouputStream = response.getOutputStream();
response.setContentType(getServletConfig().getInitParameter("contentType");
final List<File> filesToMerge = getFiles(getServletContext().getRealPath(getServletConfig().getInitParameter("includeDirectory")));
for (final File fileToMerge : filesToMerge) {
final FileInputStream inputStream = new FileInputStream(fileToMerge);
IOUtils.copy(inputStream, ouputStream);
inputStream.close();
}
ouputStream.close();
}
</pre>
<li>For example, if your optimizer plugin aggregates your javascript files to "/javascript/bundle.js", we must overwrite this URL via a servlet mapping.<br />We just create a second web.xml (this is just for localhost and jetty) with the name "web-localhost.xml" in your "src/main/webapp/WEB-INF" directory with the following servlet mapping</li>
<pre class="brush:xml;"><servlet>
<servlet-name>Merge Javascript Servlet</servlet-name>
<servlet-class>xxx.servlet.MergeResourceServlet</servlet-class>
<init-param>
<param-name>includeDirectory</param-name>
<param-value>/javascript/</param-value>
</init-param>
<init-param>
<param-name>contentType</param-name>
<param-value>application/x-javascript</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Merge Javascript Servlet</servlet-name>
<url-pattern>/javascript/bundle.js</url-pattern>
</servlet-mapping>
</pre>
<li>Now we configure jetty to use our "web-localhost.xml" as overrideDescriptor</li>
<pre class="brush:xml;"><plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<webAppConfig>
<overrideDescriptor>src/main/webapp/WEB-INF/web-localhost.xml</overrideDescriptor>
</webAppConfig>
...
</configuration>
</plugin></pre>
</ul>
</ul>
Finished! You will be able to start jetty now via "mvn package -P jetty-run".
Unknownnoreply@blogger.com7tag:blogger.com,1999:blog-2618984073208482411.post-86461268718042017222012-10-03T11:25:00.003-07:002012-10-03T11:50:04.615-07:00Introducing PrimeFaces ExtensionsIn march 2011, I founded my first open source project called "<a href="http://code.google.com/p/primefaces-extensions/">PrimeFaces Extensions</a>".<br />
<br />
Our new application required a functionality to resize/rotate images and select a part of the image to do OCR (<span class="st"><i>Optical Character Recognition)</i></span>, both with client-server communication.<br />
<br />
I already had experience with JSF2 and PrimeFaces 2.2, so I decided to develop those components in my spare time based on PrimeFaces and commit it to a open source platform (Google Code).<br />
<br />
After talking to Cagatay Civici (PrimeFaces founder and lead developer), I got green light to start the "PrimeFaces Extensions" project.<br />
<br />
The first release contained this two components: ImageRotateAndResize and ImageAreaSelect.<br />
<br />
Months later Oleg Varaksin joined my project as second lead and developer.<br />
For the first big release (0.2), we developed many new components like CKEditor, MasterDetail, ResetInput and Layout.<br />
<br />
<br />
Nevertheless, after 1,5 years of hard work, we can proudly say that we created some really unique and useful components which are used by many PrimeFaces users and also used in real-world applications!<br />
<br />
Currently we are 6 developers around the world and we have about 25 components, functions, behaviors and converters.<br />
<br />
Also some of our components and enhancements are now part of PrimeFaces and we also have a little influence on JSF 2.2 with our ResetInput component (<a href="http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1060">JIRA Issue</a>).<br />
<br />
<br />
Thanks to Cagatay for PrimeFaces, Oleg for the great cooperation and the other PrimeFaces Extensions developers for their great work!Unknownnoreply@blogger.com7tag:blogger.com,1999:blog-2618984073208482411.post-90375018282524361412012-09-06T14:02:00.001-07:002013-02-10T09:33:37.827-08:00Increase your JSF application performance (Part 2 - Design Patterns)<ul>
<li>Use Facelets instead of JSP </li>
<li>If possible, always use HTML instead of JSF tags </li>
<li>Never put logic in getters because they can be called multiple times - especially for the rendered attribute</li>
<li>Avoid much logic in EL expression</li>
<li>Avoid using h:outputText. Just use EL expressions. If you need to escape HTML, it's better to use a EL function</li>
<li>Use AJAX as much as possible </li>
<li>Only process and update components which are really required to process or update</li>
<li>Cache data, which is required multiple times in the same view, in @RequestScoped beans</li>
<li>Avoid using @SessionScoped, @ViewScoped and other long living scopes</li>
<li>Split your beans. Its better to have a seperate bean for logic and a seperate bean for values which are required for multiple requests (@ViewScoped, @ViewAccessScoped...). I call them *Controller and *StateHolder</li>
</ul>
Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-2618984073208482411.post-69161090354798190322012-08-24T12:55:00.000-07:002012-11-06T10:16:18.516-08:00Get bean instance in CDIIn some cases it's required to get the bean instance instead of the reference.<br />
You can simply do it with the following method:<br />
<br />
<pre class="brush: java">public static <T> T getBeanInstance(final Class<T> type, final Class<? extends Annotation> scope, final BeanManager beanManager)
{
final Context context = beanManager.getContext(scope);
final Set<<Bean<?>> beans = beanManager.getBeans(type);
final Bean<T> bean = (Bean<T>) beanManager.resolve(beans);
final CreationalContext<T> creationalContext = beanManager.createCreationalContext(bean);
return context.get(bean, creationalContext);
}
</pre>
Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-2618984073208482411.post-19572428061634192742012-08-21T14:03:00.000-07:002016-01-28T02:33:28.570-08:00Increase your JSF application performance (Part 1 - Environment & Configuration)<ul>
<li>Always use the newest MyFaces version (As you can read here: <a href="http://lu4242.blogspot.de/2012/05/understandingjsf-2-and-wicket.html">Blog Entry</a>)</li>
<li>If you just need a plain servlet container, use Tomcat instead of Jetty</li>
<li>Use JUEL as EL implementation </li>
<ul>
<li>Add the newest JUEL API + implementation as depedency</li>
<li>Configure MyFaces to use JUEL:</li>
<pre class="brush:xml;"><context-param>
<param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
<param-value>de.odysseus.el.ExpressionFactoryImpl</param-value>
</context-param></pre>
</ul>
<li>Increase expression cache in JUEL</li>
<ul>
<li>Create <i>src/main/resources/el.properties</i></li>
<li>Add property <i>javax.el.cacheSize</i> with a custom size. The default size is <i>1000</i>. In my application i use a size of <i>3000</i>.</li>
</ul>
<li>If you use CDI, consider to use OpenWebBeans as implementation and configure this in your web.xml:</li>
<pre class="brush:xml;"><context-param>
<param-name>org.apache.myfaces.EL_RESOLVER_COMPARATOR</param-name>
<param-value>org.apache.myfaces.el.unified.OpenWebBeansELResolverComparator</param-value>
</context-param></pre>
<li>Enable MyFaces EL caching as described in <a href="https://cwiki.apache.org/MYFACES/cache-el-expressions.html">MyFaces Wiki</a></li>
<li>Disable JSP support in MyFaces:</li>
<pre class="brush:xml;"><context-param>
<param-name>org.apache.myfaces.SUPPORT_JSP_AND_FACES_EL</param-name>
<param-value>false</param-value>
</context-param></pre>
Attention: If you set this, you need to provide the "org.apache.myfaces.EXPRESSION_FACTORY" parameter.
<li>Other params to increase performance:</li>
<pre class="brush:xml;"><context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Production</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
<param-value>-1</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.CHECK_ID_PRODUCTION_MODE</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.VIEW_UNIQUE_IDS_CACHE_ENABLED</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.SAVE_STATE_WITH_VISIT_TREE_ON_PSS</param-name>
<param-value>false</param-value>
</context-param>
</pre>
<li>Configure state management as described in <a href="http://wiki.apache.org/myfaces/Performance">MyFaces Wiki</a></li>
<li>Use a custom ServletFilter to set the correct expires/cache headers of your resources (images, stylesheets, javascripts)</li>
<li>Compress and optimize your Javascripts in your build process. If you use maven, try primefaces-extensions' closure compiler maven plugin</li>
</ul>
Unknownnoreply@blogger.com12tag:blogger.com,1999:blog-2618984073208482411.post-7771856793013406542012-08-20T13:07:00.003-07:002013-09-19T05:38:25.365-07:00Enable failover with OpenWebBeans (> 1.1.3)With Tomcat 7.0.22, some changes has be done when <br />
<br />
<pre class="brush:java;"> ServletRequestListener
#requestDestroyed(javax.servlet.ServletRequestEvent)
</pre>
<br />
will be called. This caused that session replication was done before OpenWebBeans prepared the beans for the failover.<br />
<br />
Therefore a new ServletFilter, which prepares the bean failover before session replication, was added in OpenWebBeans 1.1.4.<br />
<br />
Just add it as FIRST filter in your web.xml:<br />
<br />
<pre class="brush:xml;">org.apache.webbeans.web.failover.FailOverFilter
</pre>
<br />
and map it for example to the FacesServlet.<br />
<br />
Also don't forget the src/main/resources/META-INF/openwebbeans/openwebbeans.properties with following entries:<br />
<br />
<pre class="brush:xml;"> configuration.ordinal=100
org.apache.webbeans.web.failover.issupportfailover=true
org.apache.webbeans.web.failover.issupportpassivation=true
</pre>
<br />
<br />
Update for OWB 1.2.0 -> <a href="http://tandraschko.blogspot.de/2013/09/enable-failover-with-openwebbeans-120.html">Click</a>Unknownnoreply@blogger.com7