mercredi 19 février 2014

JSP, JS, CSS hot-deployment with Maven in Eclipse WTP

Eclipse WTP use Adtaper to provide hot deploy fonctionnalities with JEE application servers or web containers. Depending on the configuration, the adapter may reload the whole .war or .ear and take several seconds when not minutes to do so.

While WTP adatpers hot deployment is a time-saver as it rely on the Eclipse incremental compiler and does not pass through all the maven build phase to package the final .war or .ear, this is not the good choice when you work with resources like .jsp, .js, .css, .html, .tag, ...

For those static resources that don't need the whole application context to be reloaded a faster way is to copy themn automatically to the application server work directory. Some benefits are :
  • save time : no .war or .ear undeploy/redeploy
  • use [F5] to reload your resource instantly
    • the session is kept
    • the context is alive (jBPM, Spring web flow, DROOLS)
  • no more OutOfMemory or PermGenSpace when redeploying...
Next lines will show you how to set it up under JonAS. This HowTo is based on JonAS 5.2.4, Sun JKD 1.7, Maven 3.1.1, Windows 7 and Eclipse Juno. This should work on other OS as long as you go with Maven 3 and might be ported to other application servers...

WTP Adapter configuration

First of all, you need to tell JonAS WTP adatper not to publish automatically. The option is available when you double-click on the application server icons in the Eclipse "Servers" view :


Choose "Never publish automatically"... You'll then need to undeploy/deploy manually (remove and publish from the Eclipse "servers" view) when you want a code change to be taken in account or setup Cargo and configure the cargo:deploy goal to publish changes for you.

JonAS configuration

By default, JonAS will create a new directory each time an EAR or WAR is deployed. What we want is JonAS to use the same directory each time it deploys the same file, so we need to set the jonas.development property to false in the jonas.properties configuration file :

#  Set to true in order to execute the JOnAS Server in development mode.
#
#  WAR archive deployment case in development mode (for single or EAR packaged WARs):
#  Each modified WAR archive will be unpacked in the working directory of the 
#  JOnAS Server in a different folder to avoid file locks. 
#  This is especially useful in a Windows environment.
jonas.development    false
JonAS will then use a directory named against Eclipse project name.

Maven settings.xml configuration

As of Maven 3.0, profiles in the POM can also be activated based on properties from active profiles from the settings.xml.
As we want this trick to be a per user configuration we are going to rely on a property defined in the user's settings.xml to activate the static resource hot deployment :
<profile>
    <id>project-static-resources-hot-deploy</id>
    <activation>
        <activeByDefault>true</activeByDefault>
        <file>
            <exists>D:\PROJECT\jonas-full-5.2.4</exists>
        </file>
    </activation>
    <properties>
        <project.static.resources.hot.deploy.path>D:\PROJECT\jonas-full-5.2.4\work\webapps\jonas\single\{directory}</project.static.resources.hot.deploy.path>
    </properties>
</profile>
The {directory} part of the property must point to the WTP adapter deploy path for the desired Eclipse project.

Project configuration

Then we just need to add a profile activated based on the property defined in the user settings.xml that will trigger the use of the maven-resources-plugin to copy selected static resources to the application deployment path under JonAS. The copy is executed each time a static resource is saved in Eclipse and rely on the Maven Integration (m2e) for Eclipse.
<profile>
    <id>static-resources-hot-deploy</id>
    <activation>
        <property>
            <name>project.static.resources.hot.deploy.path</name>
        </property>
    </activation>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <id>static-resources-hot-deploy</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.static.resources.hot.deploy.path}</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>src/main/webapp</directory>
                                    <!-- if you use filtering in your build use true -->
                                    <filtering>false</filtering>
                                    <!-- whatever extension you want to copy -->
                                    <includes>
                                        <include>**/*.css</include>
                                        <include>**/*.jsp</include>
                                        <include>**/*.js</include>
                                        <include>**/*.tag</include>
                                    </includes>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

Troubleshooting

Sometimes, Eclipse ignore user settings.xml and does not activate project profiles based on settings.xml properties. As a workaround, you can :
  1. verify that Eclipse points to the correct user settings.xml in the following Eclipse menu Settings -> Maven -> Installations (you may need to restart Eclipse after changing this setting).
  2. add the profile that set the property directly in the project pom. 

samedi 9 mars 2013

Generate Android image resources from SVG with Maven

I recently wrote the AndroidGenDrawable Maven plugin for Android that allow you to generate density specific PNG drawable from SVG (scalable vector graphics) at build time for your Android projects. Here is a brief presentation.

Fragmentation

Fragmentation is an actual problem when speaking of Android development. Specially when programmers need to maintain density specific raster graphics image (bitmaps) to target all of the possible Android device screens. The very first example is the Launcher icon of an Android application that should be resized depending on the generalized screen density (see link) :

ldpi generalized density
mdpi generalized density
hdpi generalized density
xhdpi generalized density

androidgendrawable-maven-plugin

The androidgendrawable maven plugin allow you to work on a unique SVG version of your assets and to generate the density specific PNG versions required by the Android runtime at build time. The SVG artwork are automatically scaled and transcoded to PNG for you during the maven build. The plugin rely on apache batik to transcode the SVG to PNG. You just have to add the plugin declaration and its configuration to your pom.xml :
<plugin>
 <groupId>fr.avianey.modjo</groupId>
 <artifactId>androidgendrawable-maven-plugin</artifactId>
 <version>1.0-SNAPSHOT</version>
 <configuration>
  <from>${project.basedir}/svg</from>
  <to>${project.basedir}/res</to>
  <rename>
   <level>icon</level>
  </rename>
  <createMissingDirectories>true</createMissingDirectories>
  <targetedDensities>
   <density>ldpi</density>
   <density>mdpi</density>
   <density>hdpi</density>
   <density>xhdpi</density>
  </targetedDensities>
  <fallbackDensity>mdpi</fallbackDensity>
  <skipNoDpi>true</skipNoDpi>
 </configuration>
 <executions>
  <execution>
   <phase>initialize</phase>
   <goals>
    <goal>gen</goal>
   </goals>
  </execution>
 </executions>
<plugin>
Required resources are then generated during the initialize phase of the Maven build :
[INFO] ------------------------------------------------------------------------
[INFO] Building level 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- androidgendrawable-maven-plugin:1.0-SNAPSHOT:gen (default) @ level ---
[INFO] Transcoding level-xhdpi.svg to drawable
[INFO] Transcoding level-xhdpi.svg to drawable-hdpi
[INFO] Transcoding level-xhdpi.svg to drawable-ldpi
[INFO] Transcoding level-xhdpi.svg to drawable-xhdpi
You can fork the plugin on github here and read the documentation on the associated github page here.

mardi 5 février 2013

The Facebook Android API v3.0 on Maven

For those of you that might be interrested, I just created a Maven repository that hosts my Maven port of the Facebook Android API in its latest v3.0 version. You just need to reference the GitHub pages hosted repository in you Android Maven project pom.xml :
<repositories>  
  ...  
  <repository>  
    <id>The mavenized Facebook Android API</id>  
    <url>http://avianey.github.com/facebook-api-android-maven/</url>  
  </repository>  
</repositories>
...and to import the facebook-android-api as a dependency :
<dependencies>
  ...
  <dependency>
    <groupId>com.github.avianey</groupId>
    <artifactId>facebook-android-api</artifactId>
    <version>3.0.0</version>
    <type>apklib</type>
  </dependency>
</dependencies>
I picked the groupId to avoid conflict with other ports one might find on the Internet. As usual, you can fork this mavenized Facebook Android API on GitHub.
Fork me on GitHub