Saturday, December 29, 2012

Setting Up logentries for OSGi Applications in Apache Karaf

What You'll Get

-->

How To

Get an account at logentries. For a start, you'll get free forever account for 1 GB of logs per month, which is cool. :-)
We need to patch leappender-1-1.5.jar by adding OSGi manifest headers and attach it as fragment to pax-logging-service. (in CentOS/Amazon Linux, jar requires java-1.7.0-openjdk-devel yum package)
wget 'https://github.com/downloads/logentries/le_java/leappender-1.1.5.jar'unzip -d leappender leappender-1.1.5.jarmkdir -vp leappender/META-INF
nano leappender/META-INF/MANIFEST.MF
Replace with:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: com.logentries.leappender
Bundle-SymbolicName: com.logentries.leappender
Bundle-Version: 1.1.5
Created-By: 1.7.0_09-icedtea (Oracle Corporation)
Export-Package: com.logentries.log4j;uses:="org.apache.log4j.spi";version="1.1.5"
Import-Package: org.apache.log4j,org.apache.log4j.spi
Fragment-Host: org.ops4j.pax.logging.pax-logging-service
rm -v leappender-1.1.5.bar; jar -cvfm leappender-1.1.5.bar leappender/META-INF/MANIFEST.MF -C leappender .
# Wrap it first using bnd
wget -O bnd.jar 'http://search.maven.org/remotecontent?filepath=biz/aQute/bnd/1.50.0/bnd-1.50.0.jar'
java -jar bnd.jar wrap leappender-1.1.5.jar


our appender bundle should be present in the system folder and defined in etc/startup.properties.
The system folder has a “Maven repo like” structure. So you have to copy with:

system/groupId/artifactId/version/artifactId-version.jar


In our example, it means:
mkdir -vp system/com/logentries/leappender/1.1.5/cp -v leappender-1.1.5.bar system/com/logentries/leappender/1.1.5/leappender-1.1.5.jar
and in etc/startup.properties, we define the appender bundle just before the pax-logging-service bundle:
...
org/ops4j/pax/logging/pax-logging-api/1.
7.0/pax-logging-api-1.7.0.jar=8com/logentries/leappender/1.1.5/leappender-1.1.5.jar=8 org/ops4j/pax/logging/pax-logging-service/1.7.0/pax-logging-service-1.7.0.jar=8
...
Edit Karaf's etc/org.ops4j.pax.logging.cfg :
log4j.rootLogger = INFO, out, le, osgi:*
...
# Logentries appender
log4j.appender.
le=com.logentries.log4j.LeAppender
log4j.appender.
le.Token=LOGENTRIES_TOKEN
log4j.appender.
le.Debug=true
log4j.appender.
le.layout=org.apache.log4j.PatternLayout
log4j.appender.
le.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
#
log4j.appender.le.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss ZZZ} %-5p: %F:%L %m
Note: The LOGENTRIES_TOKEN parameter can be found beside the logfile which we created earlier.
I can't get this to work automatically, so on first Karaf launch you'll get ClassNotFoundException, then you'll need to install it:
install mvn:com.logentries/leappender/1.1.5
bundle-level <id> 8
Now it should work.
At first launch you'll get a ClassNotFound exception. Shutdown Karaf and relaunch, it should work. (this was due to the leappender-1.1.5.jar in deploy/ folder, the system one still doesn't work automatically)
Happy logging! :-)
References:

Sunday, July 15, 2012

Using Javassist to Create a Karaf/GoGo Shell Command Dynamically

Karaf OSGi runtime provides an excellent shell console functionality called Felix GoGo that can be extended easily using Blueprint XML :

<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0">
    <command name="process/run">
        <action class="com.soluvas.process.shell.ProcessRunCommand">
            <argument ref="processContainer"/>
            <argument ref="ksession"/>
            <argument ref="dependencyLookup"/>
        </action>
    </command>
    <command name="process/ls">
        <action class="com.soluvas.process.shell.ProcessLsCommand">
            <argument ref="processContainer"/>
        </action>
    </command>
    <command name="process/class">
        <action class="com.soluvas.process.shell.MakeClassCommand">
            <argument ref="blueprintBundleContext"/>
        </action>
    </command>
</command-bundle>

A Karaf Shell Blueprint command element is equivalent to:

<bean id="processLsCommand" scope="prototype"

class="com.soluvas.process.shell.ProcessLsCommand">

<argument ref="processContainer"/>

</bean>

<service auto-export="interfaces">

<service-properties>

<entry key="osgi.command.scope" value="test"/>

<entry key="osgi.command.function" value="ls"/>

</service-properties>

<bean class="org.apache.karaf.shell.console.commands.BlueprintCommand">

<property name="blueprintContainer" ref="blueprintContainer"/>

<property name="blueprintConverter" ref="blueprintConverter"/>

<property name="actionId"><idref component-id="processLsCommand"/></property>

</bean>

</service>


Using the bytecode tooling library Javassist, it's possible (and almost quite practical) to create GoGo commands dynamically at runtime :

ClassPool pool = new ClassPool();
pool.appendClassPath(new LoaderClassPath(getClass().getClassLoader()));

CtClass helloClass = pool.makeClass("cc.HelloCommand");
helloClass.setSuperclass(pool.get("org.apache.karaf.shell.console.OsgiCommandSupport"));
helloClass.addInterface(pool.get("org.apache.karaf.shell.console.CompletableFunction"));
helloClass.addInterface(pool.get("org.apache.felix.service.command.Function"));

ClassFile cf = helloClass.getClassFile();
AnnotationsAttribute attr = new AnnotationsAttribute(cf.getConstPool(), AnnotationsAttribute.visibleTag);
Annotation annotation = new Annotation("org.apache.felix.gogo.commands.Command", cf.getConstPool());
annotation.addMemberValue("scope", new StringMemberValue("test", cf.getConstPool()));
annotation.addMemberValue("name", new StringMemberValue("hello", cf.getConstPool()));
annotation.addMemberValue("description", new StringMemberValue("Hello!", cf.getConstPool()));
attr.addAnnotation(annotation);
cf.addAttribute(attr);

CtMethod doExecuteMethod = CtMethod.make("protected Object doExecute() throws Exception { System.out.println(\"OMG!\"); return \"Hello!\"; }", helloClass);
helloClass.addMethod(doExecuteMethod);

System.out.println("Class: " + helloClass);
Class clazz = helloClass.toClass(getClass().getClassLoader(), getClass().getProtectionDomain());
System.out.println("Created " + clazz);
final Object obj = clazz.newInstance();

BlueprintCommand cmd = new BlueprintCommand() {
    @Override
    public Action createNewAction() {
        return (Action)obj;
    }
};
Hashtable<String, String> props = new Hashtable<String, String>();
props.put(CommandProcessor.COMMAND_SCOPE, "test");
props.put(CommandProcessor.COMMAND_FUNCTION, "hello");
bundleContext.registerService(new String[] { CompletableFunction.class.getName(),
                Function.class.getName() }, cmd, props);

return null;

Saturday, April 14, 2012

Just found out @neo4j built-in webadmin graph visualization supports custom labels and *icons* (!!!) How come nobody told me before about this? ;-) AWESOME!

Neo4j-webadmin-visualization

Just found out @neo4j built-in webadmin graph visualization supports custom labels and *icons* (!!!) How come nobody told me before about this? ;-) AWESOME!

Thursday, March 29, 2012

Workaround for Compilation Errors when Implementing Authenticator in Seam Security and PicketLink IDM

Due to SEAMSECURITY-66 bug, compiling Authenticator implementation will result in compilation errors, as of Seam Security 3.1.0.Final and PicketLink IDM 1.5.0.Alpha2:

[INFO] Compiling 22 source files to /home/ceefour/git/aksimata-web/target/classes [INFO] ------------------------------------------------------------- [ERROR] COMPILATION ERROR : [INFO] ------------------------------------------------------------- [ERROR] LdapAuthenticator.java:[10,30] cannot find symbol symbol : class BaseAuthenticator location: package org.jboss.seam.security [ERROR] LdapAuthenticator.java:[12,34] package org.picketlink.idm.impl.api does not exist [ERROR] LdapAuthenticator.java:[13,40] package org.picketlink.idm.impl.api.model does not exist [ERROR] LdapAuthenticator.java:[23,39] cannot find symbol symbol: class BaseAuthenticator public class LdapAuthenticator extends BaseAuthenticator { [ERROR] LdapAuthenticator.java:[35,22] cannot find symbol symbol : class PasswordCredential location: class org.soluvas.ldap.LdapAuthenticator [ERROR] LdapAuthenticator.java:[46,4] cannot find symbol symbol : class SimpleUser location: class org.soluvas.ldap.LdapAuthenticator [ERROR] LdapAuthenticator.java:[46,26] cannot find symbol symbol : class SimpleUser location: class org.soluvas.ldap.LdapAuthenticator [ERROR] LdapAuthenticator.java:[48,14] cannot find symbol symbol : variable AuthenticationStatus location: class org.soluvas.ldap.LdapAuthenticator [ERROR] LdapAuthenticator.java:[51,14] cannot find symbol symbol : variable AuthenticationStatus location: class org.soluvas.ldap.LdapAuthenticator [ERROR] LdapAuthenticator.java:[52,4] cannot find symbol symbol : method setUser(<nulltype>) location: class org.soluvas.ldap.LdapAuthenticator [ERROR] LdapAuthenticator.java:[56,13] cannot find symbol symbol : variable AuthenticationStatus location: class org.soluvas.ldap.LdapAuthenticator [ERROR] LdapAuthenticator.java:[57,3] cannot find symbol symbol : method setUser(<nulltype>) location: class org.soluvas.ldap.LdapAuthenticator [ERROR] LdapAuthenticator.java:[30,1] method does not override or implement a method from a supertype

Workaround and the "proper" way to include Seam Security is as follows:

<properties>         <seam.version>3.1.0.Final</seam.version> </properties> <dependencyManagement> <dependencies>         <dependency>                 <groupId>org.jboss.seam</groupId>                 <artifactId>seam-bom</artifactId>                 <version>${seam.version}</version>                 <type>pom</type>                 <scope>import</scope>         </dependency>         <dependency>                 <groupId>org.jboss.seam.security</groupId>                 <artifactId>seam-security</artifactId>                 <version>${seam.version}</version>                 <scope>compile</scope>         </dependency>         <dependency>                 <groupId>org.picketlink.idm</groupId>                 <artifactId>picketlink-idm-core</artifactId>                 <version>1.5.0.Alpha02</version>                 <scope>compile</scope>         </dependency> </dependencies> </dependencyManagement>

In addition to the actual dependency:

<dependencies>
       <dependency>
            <groupId>org.jboss.seam.security</groupId>
            <artifactId>seam-security</artifactId>
        </dependency>
</dependencies>


To learn more about Java Web Development using Java EE 6, I highly recommend The Java EE 6 Tutorial: Basic Concepts (4th Edition) (Java Series) by Eric Jendrock, Ian Evans, Devika Gollapudi and Kim Haase.

How to Deploy Maven Artifacts to WebDAV Repository

Either the DAV wagon is great or DreamHost's Svn+WebDAV integration is great, or both. POM Configuration is straightforward:

<distributionManagement>
<snapshotRepository>
<id>soluvas.org.snapshots.tmp</id>
<url>dav:http://maven.soluvas.org/snapshots</url>
</snapshotRepository>
</distributionManagement>

It "works" in Eclipse sometimes, but when the artifact has not yet been uploaded (huh?!?!) it fails with:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.5:deploy (default-deploy) on project soluvas-apacheds: Failed to deploy artifacts: Could not find artifact org.soluvas.apacheds:soluvas-apacheds:jar:1.0.0-20120329.222133-1 in soluvas.org.snapshots.tmp (dav:http://maven.soluvas.org/snapshots) -> [Help 1]

In mvn CLI, it simply fails: [ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.5:deploy (default-deploy) on project soluvas-apacheds: Failed to deploy artifacts/metadata: No connector available to access repository soluvas.org.snapshots.tmp (dav:http://maven.soluvas.org/snapshots) of type default using the available factories WagonRepositoryConnectorFactory -> [Help 1]

Anyway, to properly do this you need a wagon config, which works well with DreamHost's subversion+webDAV (haven't tried with plain Webdav repository yet, but should work):
<build>
<extensions>
<extension>
<artifactId>wagon-webdav-jackrabbit</artifactId>
<groupId>org.apache.maven.wagon</groupId>
<version>2.2</version>
</extension>
</extensions>
</build>

then you add your credentials in ~/.m2/settings.xml :

<settings 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/xsd/settings-1.0.0.xsd">


<servers>

<server>

<id>soluvas.org.snapshots.tmp</id>

<username>youruser</username>

<password>yourpass</password>

</server>

</servers>

...

</settings>

Now you can deploy your Maven project by:

mvn source:jar javadoc:jar install deploy


To learn more about Java Web Development using Java EE 6, I highly recommend The Java EE 6 Tutorial: Basic Concepts (4th Edition) (Java Series) by Eric Jendrock, Ian Evans, Devika Gollapudi and Kim Haase.

How to Enable Gzip HTTP Compression in JBoss AS 7.1.1

JBoss AS 7.1.1 has finally returned the powerful Gzip HTTP Compression support (AS7-2991) that was missing since 7.0.0.

Edit standalone/configuration/standalone.xml and add <system-properties> after the </extensions> :

... <extension module="org.jboss.as.weld"/> </extensions> <system-properties> <property name="org.apache.coyote.http11.Http11Protocol.COMPRESSION" value="on"/> </system-properties>

Proof :

$ curl --head --compressed http://localhost:9080/
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"2432-1331360042000"
Last-Modified: Sat, 10 Mar 2012 06:14:02 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Content-Encoding: gzip
Vary: Accept-Encoding
Date: Fri, 30 Mar 2012 00:40:36 GMT

If you're running your app on OpenShift, it doesn't hurt to enable this switch now. That way, when OpenShift upgrades to JBoss AS 7.1.1 or later, your app will get HTTP Compression automatically. :-)

Alternative: You can also enable it by adding to the server launch params :

-Dorg.apache.coyote.http11.Http11Protocol.COMPRESSION=on

Enables HTTP compression on JBoss 7.1.1


To learn more about Java Web Development using Java EE 6, I highly recommend The Java EE 6 Tutorial: Basic Concepts (4th Edition) (Java Series) by Eric Jendrock, Ian Evans, Devika Gollapudi and Kim Haase.

Optimal Java EE Webapp Logging Configuration for JBoss AS7 Deployment

I used to configure logging (via SLF4J) in my Java EE web applications like this:

<properties>
    <slf4j.version>1.6.4</slf4j.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${slf4j.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-jdk14</artifactId>
            <version>${slf4j.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-jdk14</artifactId>
    </dependency>
</dependencies>

Although in practice this works well, it's not efficient because I'm bundling my own SLF4J libraries with my webapp, and direct them to JDK Logging, which is handled properly by JBoss AS 7.1.

Note that there's nothing wrong with the above configuration, because makes the webapp very portable across Application Servers (even servlet containers like Tomcat).

Thanks to Joshua Davis, I got the perfect logging configuration for JBoss AS7:

<properties>        <slf4j.version>1.6.4</slf4j.version></properties>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>commons-logging</groupId>

<artifactId>commons-logging</artifactId>

<version>1.1.1</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<version>${slf4j.version}</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>jcl-over-slf4j</artifactId>

<version>${slf4j.version}</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-jdk14</artifactId>

<version>${slf4j.version}</version>

<scope>provided</scope>

</dependency>

</dependencies>

</dependencyManagement>

Dependencies:

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>jcl-over-slf4j</artifactId>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-jdk14</artifactId>

</dependency>


Since SLF4J is already defined as a JBoss 'module', then all that we need to do is to reference the module from the WAR file.1 The simplest way is to get Maven to list the dependency in META-INF/MANIFEST.MF:

<plugin>

  <groupId>org.apache.maven.plugins</groupId>

  <artifactId>maven-war-plugin</artifactId>

  <version>2.2</version>

  <configuration>

    <archive>

      <manifestEntries>

        <Dependencies>org.slf4j, org.apache.commons.logging</Dependencies>

      </manifestEntries>

    </archive>

  </configuration>

</plugin>

This will generate a META-INF/MANIFEST.MF file that has this line in it:

Dependencies: org.slf4j, org.apache.commons.logging


This tweak saves space, RAM, and probably increases webapp performance a bit too. :-)


To learn more about Java Web Development using Java EE 6, I highly recommend The Java EE 6 Tutorial: Basic Concepts (4th Edition) (Java Series) by Eric Jendrock, Ian Evans, Devika Gollapudi and Kim Haase.

 
Copyright 2009 Spring vs Java EE Web Dev. Powered by Blogger Blogger Templates create by Deluxe Templates. WP by Masterplan