[Java] JPA und Boolean-Werte
Zwei Posts, wie man mittels JPA Boolean-Werte in der Datenbank abbilden kann.
http://www.mindbug.org/2008/03/type-conversion-with-jpa.html
http://en.wikibooks.org/wiki/Java_Persistence/Basic_Attributes
Zwei Posts, wie man mittels JPA Boolean-Werte in der Datenbank abbilden kann.
http://www.mindbug.org/2008/03/type-conversion-with-jpa.html
http://en.wikibooks.org/wiki/Java_Persistence/Basic_Attributes
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:
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:
Nachfolgend ein einfaches Beispiel, wie eine konkrete Implementierungen aussehen kann:
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(); }
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; } }
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; } }
Wenn mal Probleme hat mit oben genannten Technologien, hilft einem vielleicht der Hinweis unter http://stackoverflow.com/questions/3824431/problem-with-resteasy-and-json weiter.
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.
Um mit der Google+ API arbeiten zu können benötigt man folgende Dinge:
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:
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.
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.
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.
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.
Um über eine Tastatur und Maus mehrere Rechner zu steuern, gibt es mittlerweile diverse Softwarelösungen.
Einfache und kostenlos zu installierende Lösung. Funktioniert einfach und ist bei mir jetzt im Einsatz.
http://abyssoft.com/software/teleport/
Kostenlose Lösung, bei der unter Mac noch eine Konfigurationsdatei editiert werden muss.
http://synergy-foss.org/
Kommerzielle Lösung.
http://www.screenrecycler.com/
Mal eine Sammlung von Tools, die man als Java-Entwickler immer mal gebrauchen kann. Die Auflistung kann etwas Mac-lastig werden. Und der aktuelle Stand dient eher zur Entlastung meines Hirns 🙂
Bekommt man in der Eclipse-Console folgende Meldungen angezeigt:
[2011-02-14 15:35:18 - ddms]transfer error: Too many open files [2011-02-14 15:35:18 - Device]Error during Sync: Too many open files [2011-02-14 15:35:22 - ddms]ADB rejected shell command (ls -l /): closed
Dann am Besten den adb-Server neu starten:
./adb start-server
In diesem Post wird beschrieben, wie man auf seinem Mac einen Tomcat mit Autostart einrichtet und die Aufrufe über einen Apache Webserver an Tomcat weiterleiten lassen kann.
Einrichtung Tomcat
Auf aktuellen Macs ist standardmässig ein Apache 2 installiert. Dieser wird hier als Webserver genutzt.
Folgende Schritte sind zum Einrichten notwendig:
Damit läuft erstmal der Tomcat, muss aber noch manuell gestartet und gestoppt werden. Nächster Schritt ist die Einrichtung des Autostarts.
Autostart Tomcat
Mit dem Editor des Vertrauens die Datei „/Applications/tomcat/bin/launchd_wrapper.sh“ anlegen:
#!/bin/bash function shutdown() { date echo "Shutting down Confluence" $CATALINA_HOME/bin/catalina.sh stop } date echo "Starting Confluence" export CATALINA_PID=/tmp/$$ # Uncomment to increase Tomcat's maximum heap allocation # export JAVA_OPTS=-Xmx512M $JAVA_OPTS . $CATALINA_HOME/bin/catalina.sh start # Allow any signal which would kill a process to stop Tomcat trap shutdown HUP INT QUIT ABRT KILL ALRM TERM TSTP echo "Waiting for `cat $CATALINA_PID`" wait `cat $CATALINA_PID`
Nun als „root“-User die Datei „/Library/LaunchDaemons/tomcat.plist“ anlegen:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Disabled</key> <false/> <key>EnvironmentVariables</key> <dict> <key>CATALINA_HOME</key> <string>/Applications/tomcat</string> <key>JAVA_HOME</key> <string>/Library/Java/Home</string> </dict> <key>Label</key> <string>Tomcat</string> <key>OnDemand</key> <false/> <key>ProgramArguments</key> <array> <string>/Applications/tomcat/bin/launchd_wrapper.sh</string> </array> <key>RunAtLoad</key> <true/> <key>ServiceDescription</key> <string>Tomcat</string> <key>StandardErrorPath</key> <string>/Applications/tomcat/logs/launchd.stderr</string> <key>StandardOutPath</key> <string>/Applications/tomcat/logs/launchd.stdout</string> <key>UserName</key> <string>root</string> </dict> </plist>
Starten kann man den Tomcat-Service im Verzeichnis „/Library/LaunchDaemons/“ nun per:
"sudo launchctl load -w tomcat.plist"
Beendet wird der Tomcat-Service per:
"sudo launchctl unload -w tomcat.plist"
Tomcat sollte jetzt beim Starten des Macs von selbst hochfahren. Fehlt noch die Verknüpfung von Apache und Tomcat.
Verknüpfung Tomcat und Apache
Als „root“ mit einem Editor die Datei „/etc/apache2/other/tomcat.conf“ anlegen:
ProxyPass / http://localhost:8080/ ProxyPassReverse / http://localhost:8080/
Jetzt noch mal den Apachen durchstarten:
"sudo apachectl graceful"
Jetzt sollte Tomcat über den Apachen ausgeliefert werden. Ein Test im Browser sollte mit „http://localhost/“ funktionieren.
Beim Aufrufen einer Activity kann man Daten übergeben, die in der aufgerufenen Activity ausgewertet werden können. Dies können primitive Datentypen sein oder Instanzen von eigenen Klassen.
Der Aufrufer muss eine Intent-Instanz mit den entsprechenden Informationen befüllen und mit diesem Intent dann die Activity aufrufen.
01. Intent intent = new Intent( context, YourActivityClass.class );
02. YourContainerClass data = new YourContainerClass( „some usefull data“ );
03. intent.putExtra( „yourdata“, data );
04. startActivity( intent );
In Zeile 01 wird eine Intent-Instanz erzeugt. Die Activity-Klasse, die aufgerufen werden soll, heisst hier YourActivityClass.
In Zeile 02 wird von einer Klasse eine Instanz erzeugt, die als Datencontainer dient und die benötigten Informationen vom Aufrufer an YourActivityClass übergibt. Im Beispiel wird davon ausgegangen, dass der String „some usefull data“ innerhalb der Container-Instanz gespeichert wird und dadurch an YourActivityClass übergeben wird.
In Zeile 03 wird die Instanz der Container-Klasse in die Intent-Instanz übergeben. Die Container-Klasse wird dabei unter dem Schlüssel „yourdata“ abgelegt.
In Zeile 04 wird schliesslich die Activity (hier also YourActivityClass) aufgerufen.
Um die Informationen auf Seiten der aufgerufenen Activity auszulesen, wird folgender Code genutzt:
01. protected void onCreate( Bundle savedInstanceState )
02. {
03. super.onCreate( savedInstanceState );
04. Intent intent = getIntent();
05. YourContainerClass data = ( YourContainerClass )intent.getExtras().get( „yourdata“ );
06. // doing some other usefull stuff
07. }
In Zeile 01 wird der Methodenaufruf von onCreate() gezeigt, möglich wäre aber z.B. auch onStart() oder onResume().
In Zeile 04 wird das Intent-Objekt geholt, welches zum Aufruf der Activity genutzt wurde.
In Zeile 05 wird die Container-Klasse aus dem Intent-Objekt geholt, welches auf Seiten des Aufrufer-Codes unter dem Schlüssel „yourdata“ in dem Intent-Objekt abgelegt wurde.