Reporting Gradle Builds using WebSockets

If you have a build server you might want to receive reporting from your build. Many build bots offer this kind of reporting, but I decided to implement it myself in a standard Gradle build script. I override the default logger and replace it with one that writes all of the logging to a web socket. I have also created a very simple Java EE service which can consume logging messages and rebroadcast them to a different web socket using JMS¹.

Gradle Configuration

buildscript {
    dependencies {
        /* I'm using the tyrus libraries for my web socket client.
         Because logging is part of the build and not the project, 
         they must be declared classpath and in the buildscript.dependencies
         stanza.    
        */
        classpath 'org.glassfish.tyrus:tyrus-client:1.+'
        classpath 'org.glassfish.tyrus:tyrus-server:1.+'
        classpath 'org.glassfish.tyrus:tyrus-container-grizzly:1.+'
    }
}
//Now we begin the setup for the WebSocket Logger
import org.glassfish.tyrus.client.*;

gradle.useLogger(new WebSocketLogger());

class WebSocketLogger implements org.gradle.api.logging.StandardOutputListener {

    def manager = ClientManager.createClient();
    def session = manager.connectToServer(WebSocketLoggerClientEndpoint.class, java.net.URI.create("ws://localhost:8080/log_viewer/logging"));

    // useLogger replaces the default logging.  I am writing to a tmp file for debugging purposes.
    def tmp = new File('/tmp/log.txt');

    @Override
    void onOutput(CharSequence charSequence) {
        tmp.append(charSequence +"\n");
        session.basicRemote.sendText(charSequence.toString());
    }

    @javax.websocket.ClientEndpoint
    class WebSocketLoggerClientEndpoint {

        @javax.websocket.OnMessage
        public void processMessageFromServer(String message, javax.websocket.Session session) {
            tmp.append(message +"\n");
        }

        @javax.websocket.OnError
        public void handleError(javax.websocket.Session session, Throwable thr) {
            tmp.append('Err' + thr.message +"\n");
        }
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

Java EE Server

The server side was more complex because of how CDI and WebSockets interact in Java EE 7. The code is really simple and benefits much more from browsing in GitHub than in snippets here. You may view the server source here : https://github.com/secondsun/log_viewer².

All this code does is take messages sent to the socket found at “ws://localhost:8080/log_viewer/logging” and rebroadcasts them to “ws://localhost:8080/log_viewer/read”

Conclusion

Being able to rebroadcast log messages is neat and useful. Additionally having a working example for connecting websockets to JMS was a lot of fun to put together.

Foot notes

1: I would have used CDI events, but CDI and the ServerEndpoint annotation do not get along. There are several JIRAs tracking this issue.
* WEBSOCKET_SPEC-196
* JMS_SPEC-121
* CDI-370
2: Thanks to https://blogs.oracle.com/brunoborges/entry/integrating_websockets_and_jms_with for help with getting this working.

AeroGear Android 3.0

So it has been a while, but AeroGear Android 3.0 is out. As fitting a major number release we have a few breaking changes, lots of bug fixes, and a few new features. The full changelist can be viewed on our JIRA page

Changes

Breaking Changes

New Features

  • aerogear-android-push now uses GCM 3 including GcmListener, InstanceID, and GCM Topics.
  • Android 23 support
  • Material design in cookbooks

Minor Changes

  • JUnit 4 based automated tests
  • Updates to all required libraries (Android SDK, Android Maven Plugin)

How to get it

In Android Studio just declare our dependencies in your build.gradle file. Feel free to mix and match as necessary.

    compile 'org.jboss.aerogear:aerogear-android-core:3.0.0'
    compile 'org.jboss.aerogear:aerogear-android-security:3.0.0'
    compile 'org.jboss.aerogear:aerogear-android-store:3.0.0'
    compile 'org.jboss.aerogear:aerogear-android-pipe:3.0.0'
    compile 'org.jboss.aerogear:aerogear-android-auth:3.0.0'
    compile 'org.jboss.aerogear:aerogear-android-authz:3.0.0'
    compile 'org.jboss.aerogear:aerogear-android-push:3.0.1'

Also, feel free to take our cookbook samples for a spin!

How to get involved

Feel free to join us at #aerogear on IRC, follow us @aerogears on Twitter, or also join our aerogear-dev and aerogear-users mailing lists. For more details please check out our Community Page.

Android N – Security with Self Signed Certificates

If you are a good developer you are securing your services with SSL encryption. Unless you have put in a lot of effort, local testing still uses the good old fashioned self signed certificate and just click through the warning window of shame.

Screenshot from 2016-05-04 13-04-42

This is great until you are writing a RESTful service to be consumed by something which isn’t a browser. If you are an Android developer you have probably come across blog posts (or the official Android docs) encouraging you to make your own Trust Manager to accept your certificate or, worse, disable certificate checking altogether! However, Android N has come to the rescue with new security configuration features.

Using Self Signed Certificates with Android N

To use a self signed certificate you need to

  1. Add a meta-data tag to your AndroidManifest.xml which points to a security configuration xml file
  2. Add to your xml resources directory the security configuration file
  3. Download your self signed certificate to your project

Edit AndroidManifest.xml

I’ve added in my projects the following code to Android Manifest’s application element
[code lang=”xml”]
<meta-data android:name="android.security.net.config"
android:resource="@xml/network_security_config" />
[/code]

This code just informs Android that the configuration file is found in res/xml/network_security_config.xml.

Creating the Network Security Config

The full documentation for the network security files covers a lot more than our use case for a self signed certificate. It is well worth a read to understand what is being done.

Here is my XML file to load my certificate from the raw directory. I have it named server_aerogear_dev, but the file name is irrelevant. What matters is that the common name in the certificate file matches the domain name of the server. I am pretty sure that this also works with IP addresses, but I haven’t tested it.
[code lang=”xml”]
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="@raw/server_aergear_dev"/>
</trust-anchors>
</base-config>
</network-security-config>
[/code]

Downloading the certificate

You can download the certificate to the raw directory in your source using your web browser or using the command line.

[code]
cd app/src/main/res/raw;
echo -n | openssl s_client -connect server.aerogear.dev:8443 | sed -ne ‘/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p’ > server_aerogear_dev
// Credit to SO : http://serverfault.com/questions/139728/how-to-download-the-ssl-certificate-from-a-website
[/code]

Replace the name of the server and the port with configuration appropriate to you.

Final Notes

This is a very simple example of a new feature from Android N. This may change or go out of date. However, this gives us a simple was to manage security and it ALSO works within Android’s build flavor system. Take a look, and stay safe.