CXF & Heroku, one more time…


One more Apache CXF and Heroku article to push Web services to the Java PaaS… In some previous articles I explained how to create JAXWS and JAXRS service by cloning/forking/whatever git repositories. This time it is almost the same but I created a maven archetype to generate tons of maven modules quickly and to integrate them in your maven-based projects (OK cloning a repository is faster, it does not download the entire Internet as Maven does…).

Let’s do it with a screen record to check how fast it is. With my poor Internet connection and some typos, I have something running on Heroku in less than 2 min 30…

Here are the commands used in the sample above:

The archetype source code is located at https://github.com/petalslink/petalscloud-maven-archetypes and deployed on OW2 repository. Once the project is generated from the archetype, one can add his own JAXWS-annotated services and associated Spring configuration (src/main/webapp/WEB-INF/beans.xml). Generated project is also available on github at https://github.com/chamerlingdotorg/maven-heroku-jaxws-sample.

Can it really be more easy?

Maven m’a sauvé… encore!


Encore une fois Apache Maven m’a sauvé, ou presque… Je cherchais un moyen de récupérer toutes les sources des dépendances d’un module pour un faire une archive complète. Le module en question étant une distribution contenant quelques dizaines de modules gérés par Maven, la solution est de regarder ce qu’offre l’ami Maven en question. J’utilise souvent le plugin dependency pour avoir l’arbre de dépendance via le goal tree et résoudre certains conflits de versions (oui bon m2eclipse le fait surement mais je reste fan du Terminal…), et donc il me semblait bien que le plugin dependency faisait plus que ca. C’est là qu’entre en jeu le goal unpack-dependencies. Deux/trois ajustement dans le POM du projet et il est simple de récupérer les sources:

<project>
<!--...-->
  <plugins>
  		<plugin>
		        <groupId>org.apache.maven.plugins</groupId>
		        <artifactId>maven-dependency-plugin</artifactId>
		        <version>2.2</version>
		        <executions>
		          <execution>
		            <id>src-dependencies</id>
		            <phase>package</phase>
		            <goals>
		              <!-- use copy-dependencies instead if you don't want to explode the sources -->
		              <goal>unpack-dependencies</goal>
		            </goals>
		            <configuration>
		              <classifier>sources</classifier>
		              <failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
		              <outputDirectory>${project.build.directory}/sources</outputDirectory>
					  <includeGroupIds>org.ow2.petals</includeGroupIds>
		            </configuration>
		          </execution>
		        </executions>
		      </plugin>
   <!--...-->
  </plugins>
</project>

WTF Spoonlet?


Ca fait longtemps que je n’ai pas parlé de code. Qu’a cela ne tienne, dans la série « Le bon gros bug de m**** », je vous présente Spoon… Dans un élan de refactoring, je me suis mis à extraire une vrai API du kernel de Petals DSB. L’idée est simple, le faire aurait du l’être: Extraire toutes les interfaces d’un projet A pour créer un projet A-api et en dépendre dans le projet A. Trois clics de souris et deux drag&drop plus loin, testons la compilation:

[INFO] ------------------------------------------------------------------------
[INFO] Building dsb-kernel
[INFO] task-segment: [install]
[INFO] ------------------------------------------------------------------------
[INFO] [resources:resources {execution: default-resources}]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Nothing to compile - all classes are up to date
[INFO] [spoon:recompile {execution: default}]
[INFO] org.objectweb.fractal.fraclet.annotation.processor.FractalComponentProcessor
[WARNING] FractalComponentProcessor &gt;&gt; No value found for property 'generatorClass' in processor org.objectweb.fractal.fraclet.annotation.processor.FractalComponentProcessor
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] fail to execute</code>

[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 23 seconds
[INFO] Finished at: Mon Jun 20 23:27:21 CEST 2011
[INFO] Final Memory: 50M/123M
[INFO] ------------------------------------------------------------------------

Ahah, qu’a cela ne tienne, le même en mode debug donc…

[DEBUG] Trace
org.apache.maven.lifecycle.LifecycleExecutionException: fail to execute
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:719)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:556)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:535)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:387)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:348)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:180)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:328)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:138)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:362)
at org.apache.maven.cli.compat.CompatibleMain.main(CompatibleMain.java:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
Caused by: org.apache.maven.plugin.MojoExecutionException: fail to execute
at net.sf.alchim.spoon.contrib.maven.AbstractSpoonMojo.execute(AbstractSpoonMojo.java:96)
at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:490)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:694)
... 17 more
Caused by: java.lang.NullPointerException
at spoon.support.reflect.declaration.CtAnnotationImpl.convertValue(CtAnnotationImpl.java:160)
at spoon.support.reflect.declaration.CtAnnotationImpl.getElementValue(CtAnnotationImpl.java:253)
at spoon.support.reflect.declaration.CtAnnotationImpl$AnnotationInvocationHandler.invoke(CtAnnotationImpl.java:69)
at $Proxy31.name(Unknown Source)

Yeah cool, une NPE. Ah dommage, sur $Proxy31.name… Genre le proxy généré par Spoon. Et donc bon, on fait quoi la? On revert tout et on tente de bouger les interfaces une par une pour voir qui fout son bordel? Mouais… Trève de blahblah, après avoir passé quelques dizaine de minutes à bouger, compiler, reverter, voici la conclusion: Définir des constantes dans des interfaces qui sont dans des dépendances et les utiliser dans les annotations des implémentations n’est pas possible, par exemple, dans une implémentation du style :

@FractalComponent
@Provides(interfaces = { @Interface(name = "service", signature = ServiceBinderRegistry.class) })
public class ServiceBinderRegistryImpl implements ServiceBinderRegistry {

@Requires(name = BINDER_PREFIX, signature = ServiceBinder.class, cardinality = Cardinality.COLLECTION, contingency = Contingency.OPTIONAL)
private final Map<String, Object> binders = new Hashtable<String, Object>();

On ne peut pas avoir BINDER_PREFIX dans l’interface ServiceBinderRegistry qui est dans une dépendance, par contre ca marche bien quand l’interface est dans le même projet… Quand on tombe la dessus à minuit, c’est rude…

Archetypes Petals JBI


Je pense avoir déjà fait un article sur les archetypes Petals JBI qui permettent de créer les structures de base des projets Maven pour les composants JBI et leurs artefacts de configuration (les so-called SA et SU). En cherchant un archetype dans la liste (énorme) donnée par la commande ‘mvn archetype:generate‘, je suis tombé sur ces fameux archetypes Petals JBI :

La question : Comment sont ils arrivés là? Maven introspecte t-il les artefacts sur quelque repository ou une ame bienveillante les a ajouté au fichier de configuration du plugin archetype? J’opte plus pour la première réponse…