Wildfly: JDBC-Treiber und Datasource einrichten

Ich hatte hier beschrieben, wie man eine Datasource inklusive neuem JDBC-Treiber per CLI im JBoss einrichten kann. Heute wollte ich mit einer Wildfly 8.2 Installation diese Schritte durchführen, leider funktionierte es nicht, es gibt einen Bug, der das verhindert. Eine Variante, die funktioniert, ist über die Web Management Console. Eine Anleitung habe ich hier gefunden. Nachfolgend habe ich das nochmal bei nachgestellt und Screenshots davon erstellt.

JDBC-Treiber installieren

Zuerst muss ein passender JDBC-Treiber installiert werden, falls noch nicht vorhanden. Dazu öffnet man die Managementconsole, in der Regel ist sie unter Port 9990 zu finden, bei mir lokal unter http://localhost:9990/. Falls noch kein Managementuser vorhanden ist, muss man noch einen anlegen und sich dann mit diesem anmelden. Der Applikationsserver muss natürlich laufen. Dann öffnet man den Reiter Deployments.

screenshot-localhost 9990 2015-01-04 17-26-28

Ein Klick auf den Button Add öffnet den Wizard zum hinzufügen eines neuen Deployments. Hier wählt man die JAR-Datei des entsprechenden JDBC-Treibers aus und bestätigt mit Next.

screenshot-localhost 9990 2015-01-04 17-28-17

Im folgenden Fenster kann man den Namen und den Runtime-Namen noch anpassen. Zusätzlich kann man durch Auswählen von Enable den Treiber gleich aktivieren. Die Eingaben bestätigt man durch Save.

screenshot-localhost 9990 2015-01-04 17-28-55

Der installierte JDBC-Treiber sollte jetzt angezeigt werden.

screenshot-localhost 9990 2015-01-04 17-29-24

Nun wechselt man auf den Reiter Configuration. Hier wählt man bei den Subsystems -> Connector -> Datasources aus. Falls man die Konfiguration noch nicht angepasst hat, sollte die Beispieldatasource ExampleDS noch aufgeführt werden. Um jetzt eine eigene hinzuzufügen wählt man Add aus.

screenshot-localhost 9990 2015-01-05 00-04-29

Name und JNDI Adresse der neuen Datasource werden jetzt abgefragt. Der JNDI-Name hat der Adresse zu entsprechen, die man später in der persistence.xml unter dem Element jta-data-source einträgt. Die Eingaben sind mit Next zu bestätigen.

screenshot-localhost 9990 2015-01-05 01-20-30

Hier wählt man den passenden JDBC-Treiber aus und bestätigt die Eingabe wieder mit Next.

screenshot-localhost 9990 2015-01-05 00-05-17

In diesem Fenster werden die Verbindungdaten zur Datenbank eingetragen. Mit Test Connection können die Eingaben überprüft werden. Das Anlegen der Datasource ist mit Done abzuschliessen.

screenshot-localhost 9990 2015-01-05 00-06-58

screenshot-localhost 9990 2015-01-05 00-07-16

Da die Datasource noch nicht aktiviert ist, wählt man sie aus und klickt auf Enable.

screenshot-localhost 9990 2015-01-05 00-07-39

Das Fenster mit Confirm schliessen.

screenshot-localhost 9990 2015-01-05 00-08-03

Nun steht die Datasource mit dem passenden Treiber im Wildfly zur Verfügung.

Die passenden persistence.xml, die im META-INF des WARs liegen muss, sieht bei mir so aus:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
   xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
        http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   <persistence-unit name="primary">
      <jta-data-source>java:jboss/datasources/dblocator</jta-data-source>
      <properties>
         <!-- Properties for Hibernate -->
         <property name="hibernate.hbm2ddl.auto" value="update" />
         <property name="hibernate.show_sql" value="false" />
      </properties>
   </persistence-unit>
</persistence>

Update 25.01.2015

Neuer Rechner, neues Glück. Wildfly 8.2 auf einem Ubuntu-Rechner hat jetzt noch ein anderes Verhalten an den Tag gelegt. Das Deployen eines JDBC-Treibers war dort über den oben beschriebenen Weg nicht persistent möglich. Nach jedem Neustart des Wildfly war der JDBC-Treiber weg und musste neu deployt werden.

Von JBoss gibt es hier eine gute Anleitung, wie man einen JDBC-Treiber permanent deployt. Anschliessend kann man eine Datasource einrichten, wie oben beschrieben über die webbasierte Managementconsole.

Für PostgreSQL habe ich unter wildfly/modules/org/postgres/main/modules.xml folgendes eingetragen:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="org.postgres">
  <resources>
    <resource-root path="postgresql-jdbc4-9.2.jar"/>
  </resources>
  <dependencies>
    <module name="javax.api"/>
    <module name="javax.transaction.api"/>
  </dependencies>
</module>

Unter wildfly/modules/org/postgres/main/ liegt in diesem Fall der JDBC-Treiber für Postgres mit dem Dateinamen postgresql-jdbc4-9.2.jar.

Zum Aktivieren des JDBC-Treibers für Postgres habe ich folgende Zeile in der JBoss CLI genutzt:

/subsystem=datasources/jdbc-driver=postgres:add(driver-name=postgres,driver-module-name=org.postgres,driver-xa-datasource-class-name=org.postgresql.xa.PGXADataSource)

Das JBoss CLI nutzt man, in dem man den Wildfly startet, im wildfly/bin Verzeichnis jboss-cli.sh startet und sich dann mit connect mit der Wildfly-Managementconsole verbindet.

Maven und Jetty Embedded

Ich war auf der Suche nach einem Applikationsserver oder Servletcontainer, den ich embedded laufen lassen kann. Ziel ist es, eine quasi Standalone-Webanwendung hinzubekommen, die keinen installierten Applikationsserver benötigt. Am Ende sollte ein java -jar anwendungs.jar reichen, um eine Webanwendung zu starten. Ich hab Jetty ausprobiert.

Um Jetty als embedded Servletcontainer laufen lassen zu können, habe ich folgende pom.xml zusammengestellt:

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>de.yellowshoes.jettyembedded</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>test</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>9.1.5.v20140505</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>de.yellowshoes.jettyembedded.test.HelloWorld</mainClass>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.3</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>de.yellowshoes.jettyembedded.test.HelloWorld</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Noch kurz die wichtigsten Teile der pom.xml erklärt.

Damit werden die notwendigen Jar-Dateien von Jetty als Abhängigkeiten für das Projekt definiert:

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>9.1.5.v20140505</version>
        </dependency>

Mit dem exec-maven-plugin kann man per Maven eine beliebige Javaklasse (wenn sie denn eine main-Methode implementiert) über Maven Kommandozeile aufrufen. Im Beispiel wird versucht eine Klasse de.yellowshoes.jettyembedded.test.HelloWorld aufzurufen. Der Aufruf über die Kommandozeile sieht dann beispielsweise so aus: mvn clean compile exec:java

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>de.yellowshoes.jettyembedded.test.HelloWorld</mainClass>
                </configuration>
            </plugin>

Um ein Standalone-Jar zu erzeugen, nutze ich hier das Share-Plugin. Damit wird das Jar gebaut und alle definierten Abhängigkeiten entpackt und mit ins erzeugte Jar eingefügt. Der Aufruf zum Bauen des Jar sieht so aus: mvn clean install

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.3</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>de.yellowshoes.jettyembedded.test.HelloWorld</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

Die erzeugte Jar-Datei sollte jetzt test-0.0.1-SNAPSHOT.jar heissen und mittels java -jar test-0.0.1-SNAPSHOT.jar gestartet werden können….wenn man die fehlende Klasse HelloWorld hätte 🙂

package de.yellowshoes.jettyembedded.test;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;

public class HelloWorld extends AbstractHandler {

    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        response.setContentType("text/html;charset=utf-8");
        response.setStatus(HttpServletResponse.SC_OK);
        baseRequest.setHandled(true);
        response.getWriter().println("<h1>Hello World</h1>");
    }

    public static void main(String[] args) throws Exception {
        Server server = new Server(8080);
        server.setHandler(new HelloWorld());

        server.start();
        server.join();
    }
}

Jboss: Logging einrichten

Über die JBoss CLI kann man für seine Applikationen Loggingkonfigurationen definieren, die in der Applikation genutzt werden können.

Zuerst richtet man einen Handler ein, der für das Schreiben in einer Datei zuständig ist:

/subsystem=logging/periodic-rotating-file-handler="DBLOCATOR":add(formatter="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n", append=true, file={"relative-to"=>"jboss.server.log.dir", "path"=>"dblocator.log"}, suffix=".yyyy-MM-dd", name="DBLOCATOR")

Anschliessend definiert man einen Logger, den man später in der Applikation ansprechen kann:

/subsystem=logging/logger=de.sauerspace.dblocator:add(level=INFO, handlers=["DBLOCATOR"], use-parent-handlers=false)

In der Applikation bekommt man den passenden Log4J Logger dann über folgende Anweisung:

Logger log = Logger.getLogger( "de.sauerspace.dblocator" );

 

JBoss: Datasources einrichten

Update:

Nach diversen Problemen mit dem Deployment von Treibern und Einrichten von Datasources hier noch eine andere Variante, die jetzt wohl weniger Probleme macht. Die folgenden Befehle werden im JBoss CLI ausgeführt. Dazu im bin-Verzeichnis der JBoss Installation jboss-cli.sh ausführen. Anschliessend mittels connect mit dem laufenden JBoss verbinden. Funktioniert auch mit dem Wildfly.

module add --name=org.postgresql --resources=postgresql-9.3-1100.jdbc41.jar --dependencies=javax.api,javax.transaction.api
/subsystem=datasources/jdbc-driver=postgres:add(driver-module-name=org.postgresql,driver-name=postgres,driver-class-name=org.postgresql.Driver)
/subsystem=datasources/data-source="BeispielDS":add(jndi-name="java:jboss/datasources/BeispielDS",max-pool-size=10,min-pool-size=5,driver-name="postgres",connection-url="jdbc:postgresql://localhost:5432/beispieldb",user-name="beispieluser",password="geheim")

Die Datasource kann dann unter java:jboss/datasources/beispieldb angesprochen werden.


 

Alter Text:

Um eine Datasource im JBoss einzurichten, kann man dies per JBoss CLI umsetzen.

Falls der passende Treiber für die Datenbank noch nicht installiert ist, macht man dies mit folgendem Befehl. Anschliessend ist der Treiber unter dem Namen postgres referenzierbar.

deploy postgresql-9.3-1100-jdbc4.jar --name=postgres

Eine Datasource legt man mit folgendem Befehl an:

/subsystem=datasources/data-source="DBLocator":add(jndi-name="java:jboss/datasources/dblocator",max-pool-size=10,min-pool-size=5,driver-name="postgres",connection-url="jdbc:postgresql://localhost:5432/dblocator",user-name="username",password="geheim")

 

jCIFS und OutOfMemoryExceptions

Aktuell arbeite ich mit jCIFS, einer Java-Libary für den Zugriff auf Windows-Shares. Dabei wurde in bestimmten Situationen reproduzierbar eine OutOfMemoryException geworfen. Der Stacktrace deutete auf Probleme in SmbFile.listFiles() hin. In einer Mailingliste zu Samba gab es den Hinweis, dass es ein Problem mit „Name lookup threads“ geben könnte. Da mir aufgefallen war, dass bei Ausführung des Codes die Threadanzahl von ca. 60 auf über 1000 stieg, war das ein Hinweis, der eine heisse Spur sein könnte.

Über die statische Config-Klasse wurde dann per setProperty die Reihenfolge der aufzurufenden Nameresolver geändert. Und siehe da, dann gab es keine OutOfMemoryExceptions mehr und die Threadanzahl blieb bei ca. 60. So setzt/verändert man die Reihenfolge der Nameresolver:

Config.setProperty( "jcifs.resolveOrder", "DNS,LMHOSTS,WINS" );

Wichtig war DNS an den Anfang zu setzen. Defaultmässig steht es ganz hinten.

[Android] RESTEasy und Android

Wurde eine REST-Schnittstelle auf Server-Seite mit RESTEasy implementiert, gab es bisher keine wirkliche Möglichkeit, mit RESTEasy den vorhandenen Code auch auf Android-Seite zu nutzen. RESTEasy funktionierte bisher nicht unter Android. Thomas Diesler hat glücklicherweise ein Projekt auf github (https://github.com/tdiesler/resteasy-mobile) gestartet, welches diesen Teil nachimplementiert. Er hat hierzu auch einen Blogpost verfasst.

Nachfolgende die Kurzform der notwendigen Schritte. Ich habe den Code in drei Projekte aufgeteilt:

  • REST-Interface und Transferobjekte
    In diesem Projekt werden die Transferobjekte und das REST-Interface implementiert. Transferobjekte sind die Klassen, die die Daten zwischen Server und Client kapseln. Wie der Name REST-Interface schon vermuten lässt, wird damit die Schnittstelle zwischen Client und Server definiert (aber noch nicht implementiert). Nutzt Maven.
  • REST-Server-Implementierung
    Die Implementierung der Backend-Logik. Benutzt das REST-Interface und die Transferobjekte. Nutzt Maven.
  • REST für Android
    Die Implementierung der Android-Client-Seite. Benutzt das REST-Interface und die Transferobjekte.

Für das REST-Interface und Transferobjekte wird folgende Dependency in der pom.xml eingetragen:

<dependency>
 <groupId>org.jboss.resteasy</groupId>
 <artifactId>resteasy-jaxrs</artifactId>
 <version>1.2.1.GA</version>
</dependency>

Für die REST-Server-Implementierung werden folgende Dependencies in der pom.xml eingetragen:

<dependency>
 <groupId>org.jboss.resteasy</groupId>
 <artifactId>resteasy-jaxrs</artifactId>
 <version>1.2.1.GA</version>
</dependency>

<dependency>
 <groupId>org.jboss.resteasy</groupId>
 <artifactId>resteasy-jaxb-provider</artifactId>
 <version>1.2.1.GA</version>
 </dependency>

<dependency>
 <groupId>org.jboss.resteasy</groupId>
 <artifactId>jaxrs-api</artifactId>
 <version>1.2.1.GA</version>
</dependency>

<dependency>
 <groupId>net.sf.scannotation</groupId>
 <artifactId>scannotation</artifactId>
 <version>1.0.2</version>
</dependency>

<dependency>
 <groupId>org.jboss.resteasy</groupId>
 <artifactId>resteasy-jackson-provider</artifactId>
 <version>2.3.1.GA</version>
</dependency>

<!-- Reference to REST-Interface-Project -->
<dependency>
 <groupId>de.yellowshoes.rest</groupId>
 <artifactId>restinterface</artifactId>
 <version>0.0.1-SNAPSHOT</version>
</dependency>

Auf Android-Seite ist kein Maven im Einsatz. Folgende Libraries werden im Buildpath mit aufgenommen:

  • Jackson Core ASL 1.6.3
  • Jackson JAXRS 1.6.3
  • Jackson Mapper ASL 1.6.3
  • Jackson XC 1.6.3
  • JAXRS API 2.2.1 GA von RESTEasy
  • RESTEasy Mobile 1.0.0

Nachfolgend ein einfaches Beispiel, wie eine konkrete Implementierungen aussehen kann:

REST-Interface

Zuerst die Transferklasse. Hier ein Objekt Book. Ein simples POJO, mehr nicht.

public class Book
 {
 private String titel;
 private String author;

 public String getTitel()
 {
 return titel;
 }

public void setTitel( String titel )
 {
 this.titel = titel;
 }

public String getAuthor()
 {
 return author;
 }

public void setAuthor( String author )
 {
 this.author = author;
 }
}

Nun das REST-Interface. Die @Path-Annotation definiert jeweils, an welche Url die Klasse/die Methode gebunden wird. Hier wird das komplette Interface an /api gebunden, die Methode (durch die Vererbung) an /api/book. Mit den Annotations @Consumes und @Produces wird festgelegt, was für MediaTypes verarbeitet werden können und was zurückgeschickt werden kann. Hier wird jeweils JSON definiert.

@Path( "/api" )
@Consumes( MediaType.APPLICATION_JSON )
@Produces( MediaType.APPLICATION_JSON )
public interface RestResourceInterface
 {
 @GET
 @Path( "/book" )
 public Book getBook();
 }

REST-Implementierung

Auf Server-Seite wird nur eine Klasse benötigt.

public class RestResource implements RestResourceInterface
 {
 public Book getBook()
  {
  Book book = new Book();
  book.setAuthor( "Hans Müller" );
  book.setTitel( "REST gut" );
  return book;
  }
}

REST-Android

Auch auf Android-Seite muss nicht mehr viel gemacht werden. Hier eine einfache Client-Implementierung. Das wichtigste ist die Methode getClient(), die über die ProxyFactory die Schnittstellen-Implementierung initialisiert. Der Code sollte ansonsten selbsterklärend sein.

public class ResteasyClient implements RestResourceInterface
 {
 RestResourceInterface client = null;

 @Override
 public Book getBook()
  {
  RestResourceInterface client = getClient();
  Book book = client.getBook();
  return book;
  }

 private RestResourceInterface getClient()
  {
  String requestURI = "http://192.168.11.86:8080/restest/";

  if( client == null )
   {
   BasicHttpParams params = new BasicHttpParams();
   HttpProtocolParams.setVersion( params, HttpVersion.HTTP_1_1 );
   HttpProtocolParams.setContentCharset( params, HTTP.DEFAULT_CONTENT_CHARSET );
   HttpProtocolParams.setUseExpectContinue( params, false );
   client = ProxyFactory.create( RestResourceInterface.class, requestURI, new ApacheHttpClient4Executor( params ) );
   }
  return client;
  }
 }

 

G+ API in Java nutzen

Mit diesem Blogpost soll Beschrieben werden, wie man auf der Google+ API mittels Java zugreifen kann. Da die Dokumentation von Google leider nicht so berauschend ist und auch ein wenig verstreut, trage ich hier einfach mal alles zusammen, was ich auf dem Weg zur Benutzung gefunden habe. Grund ist unter anderem, dass wir bei der GTUG RM einen kleinen Hackathon zur G+ API veranstalten.

Vorbereitung

Um mit der Google+ API arbeiten zu können benötigt man folgende Dinge:

API-Key

Zuerst registriert man sich einen API-Key. Das macht man über die Google API-Console. Bei mir sieht es nach der Registrierung dann so aus. Wichtig ist noch, das man sich eine oder mehrere Redirect URIs einträgt, die man später auch nutzt.

 

Libs

Um auf die API zugreifen zu können, benötigt man zwei Libs-Pakete von Google. Zum einen die Google APIs Client Library for Java (Stand 1.5.1 Beta) und die Google+ API (Stand 1.2.5 Beta).

Da ich kein Maven genutzt habe, musste ich die benötigten Libs manuell zusammensuchen.

Unter der Setup-Seite für die Google APIs Client Library for Java finden sich die Informationen, welche Libs grundsätzlich benötigt werden. Die abhängigen Libs (Dependencies) werde ebenfalls aufgeführt. Netterweise liefert Google alle benötigten Libs gleich mit dazu (zu finden im Unterverzeichnis dependencies der Zip-Datei).

Folgende Libs werden benötigt:

Umsetzung

OAuth

Um die G+ API nutzen zu können, braucht man zum Teil eine OAuth-basierte Autorisierung (man bekommt einen sogenannten Access-Token für die weiteren Zugriff auf die APIs) und/oder einen API-Key. Infos dazu finden sich auf der G+ API OAuth-Seite.

Für die Nutzung von OAuth stellt Google Beispielcode bereit.

Mein Beispiel ist als Web-App (für die Google Appengine) ausgelegt.

Code

Autorisierung anfordern

Um die Autorisierung und damit den Access-Token anzufordern benötigt man folgenden Code:

private void doAuthRequest(HttpServletRequest req, HttpServletResponse resp) throws IOException {
   String redirectUrl = getRedirectUrl(req);
   String authorizeUrl = new GoogleAuthorizationRequestUrl(CLIENT_ID, redirectUrl, SCOPE_GOOGLE_PLUS ).build();
   resp.sendRedirect(authorizeUrl);
}

private String getRedirectUrl( HttpServletRequest req ){
   return "http://" + req.getServerName() + ":" + req.getLocalPort() + "/start";
}

Die CLIENT_ID ist die ID als String, die man in der API-Console zugeordnet bekommen hat. SCOPE_GOOGLE_PLUS erhält den sogenannten Scope der verwendeten API als String, in diesem Fall also für die Google+ API. Der passende Scope-Wert findet sich auf der G+ OAuth-Seite und hat den Wert https://www.googleapis.com/auth/plus.me.

Autorisierungscode auslesen

Nach erfolgter Autorisierung springt die OAuth-API zurück zur angegebenen Redirect-URL. Im Erfolgsfall wird ein Code als Parameter in der URL mitgeschickt, den man ausliest und zum Abfragen eines Access-Tokens verwenden muss.

private void doAuthExtract(HttpServletRequest req, HttpServletResponse resp) throws IOException {
   String code = req.getParameter( "code" );
   HttpTransport TRANSPORT = new NetHttpTransport();
   JsonFactory JSON_FACTORY = new JacksonFactory();
   GoogleAuthorizationCodeGrant authRequest = new GoogleAuthorizationCodeGrant(TRANSPORT, JSON_FACTORY, CLIENT_ID, CLIENT_SECRET, code, getRedirectUrl(req));
   authRequest.useBasicAuthorization = false;
   AccessTokenResponse authResponse = authRequest.execute();
   String accessToken = authResponse.accessToken;

   if( session != null ){
      session.setAttribute( SESSION_PARM_ACCESS_TOKEN, accessToken);
      session.setAttribute(SESSION_PARM_REFRESH_TOKEN, authResponse.refreshToken);
      this.accessToken = accessToken;
      this.refreshToken = authResponse.refreshToken;
   }

   resp.sendRedirect( getRedirectUrl(req));
}

Somit haben wir jetzt den Access-Token und können damit auf die G+ API zugreifen.

Zugriff auf G+ API

Ein einfaches Beispiel, ohne den Bezug zur Webanwendung, der Zugriff auf die Personensuche.

Plus plus = new Plus( new NetHttpTransport(), new JacksonFactory() );
plus.setKey( API_KEY );
plus.setOauthToken( accessToken );

Search search = plus.people.search();
search.setQuery(query);
PeopleFeed peopleFeed = search.execute();

if( peopleFeed.isEmpty() == false ){
   List<Person> peopleList = peopleFeed.getItems();

   if( peopleList != null ){
      for (Person person : peopleList) {
         System.out.println( person.getDisplayName() );
      }
   }
}

API_KEY ist der API-Key, der über die Google API-Console erstellt wurde. accessToken ist der über OAuth zugewiesene Access-Token und query ist schliesslich der Suchtext.

Die Plus-Klasse (JavaDoc) ist generell der Ausgangspunkt. Über sie greift man auf die G+ API zu.

Von Seiten Google wird noch ein Starter Projekt bereitgestellt, in dem man sich den Sourcecode als Ausgangspunkt für eigene ENtwicklungen vornehmen kann.

Mein Beispielprojekt findet sich bei Google Code.