Services – UserService mit JBoss RESTlet Server

Montag, 25. August 2014 von  
unter Fachartikel Architektur

 Die Motivation

Auf dem JBoss 5.1 oder 6.1 ist mit dem Seam-Framework 2.1 oder 2.2.1 im JBoss Developer Studio schnell eine Seam-Faces Applikation zusammengestellt, die unter Verwendung von Java Server Faces (Rich Faces) als Admin Applikation ziemlich robust ist und eine angenehme Ruhe ausstrahlt.

JBoss Seam Rich Faces Admin GUI

Diese hat die folgenden Anzeige/Eingabe-Masken:

a)     Login
b)     Neuen User anlegen
c)     Alle vorhandenen User zeigen
d)     Einen ausgewählten User ändern

Mit Styles können diese Views sicherlich noch beliebig verschönert werden. Dies ist jedoch nicht Teil der diesem Blog-Eintrag zugrundeliegenden Motivation.

Zusätzlich wurde im Beispiel eine auf dem RESTlet-Framework basierende User-Registrierung innerhalb derselben Rich Faces Applikation implementiert, sie bietet also beides: sowohl für den Admin ein paar Masken, um die User-Daten zu administrieren, zu korrigieren, oder zu löschen als auch einen RESTlet WebService, so dass beliebige Clients per REST-Request in beliebige Frontends eingegebene User-Daten als User auf dem Binaris Restlet Server registrieren können.

Die Aufgabenstellung besteht im Beispiel also darin, einen User per REST-Request in der Server Datenbank einzutragen und damit zu registrieren. Die Request-Komponenten des RESTlet Requests lauten folgendermaßen:

Request-URI: http://localhost:8080/binarisRestletServer/restservice/user
Die Action: POST
Content-Type: application/json
Der Content (mit einem simplen Passwort für den REST-WebService):
{„users“:{„user“:“binaris“,
„creationdate“:“Mon Aug 06 14:20:17 CEST 2012″,
„userid“:“123456-7890112345-7890-112345-12380″,
„description“:““,
„password“:“binarisUsers“,
„knr“:“12345″,
„email“:“banana.joe@bananajoe.com“}}

Für den Test des RESTlet-basierten Servers verwendet man den Swing-basierten Test-Client aus dem bereits vorhandenen Blog-Eintrag hier oder schreibt sich selbst auf Basis der HttpClient-Klassen, z. B. unter Verwendung der apache.commons-Pakete die erforderlichen RESTful JUnit-Tests.

Bei dieser Gelegenheit darf auf das sehr gute Binaris Seminar zum Thema TDD mit Java von Binaris hier und hier hingewiesen werden, welches jede Menge wichtige und in der Praxis sehr gut zu verwendende Hinweise und nützliche Tipps sowie Übungen bietet.

Der Consolen-Output im JBoss Developer Studio zeigt den HTTP-Response Code: 200 (alles OK).

19:52:08,103 Information [org.restlet.Component.LogService] 2014-08-24    19:52:08     127.0.0.1    –       127.0.0.1    8080   POST   /binarisRestletServer/restservice/user  –      200    2      214    67298       http://localhost:8080      Jakarta Commons-HttpClient/3.1    –

Das Backend, d.h. die Datenbank, besteht in diesem Beispiel aus nur einer Tabelle. Hier die User-Tabelle “users“ der MySQL Datenbank “users_db“:

CREATE TABLE `users` (
    `iduser` INT(11) NOT NULL AUTO_INCREMENT,
    `username` VARCHAR(60) NULL DEFAULT NULL,
    `password` VARCHAR(30) NULL DEFAULT NULL,
    `userID` VARCHAR(80) NULL DEFAULT NULL,
    `knr` INT(11) NOT NULL,
    `creationDate` DATETIME NULL DEFAULT NULL,
    `description` VARCHAR(255) NULL DEFAULT NULL,
    `email` VARCHAR(60) NULL DEFAULT NULL,
PRIMARY KEY (`iduser`)
)
COLLATE=’utf8_general_ci‘
ENGINE=InnoDB
AUTO_INCREMENT=21;

(UserService auf Binaris Restlet Server: die benötigte MySQL-Tabelle users)

Die zugehörige JPA-Entity (Rich JPA Entity mit ein paar implementierten NamedQueries) ist schnell annotiert oder wird aus der Datenbank-Tabelle generiert. Dann braucht man nur noch die Named Queries (analog den JDBC-Prepared Statements) und die nützlichen Konverter-Methoden toString(), toXml() und toJson() zu implementieren und sich von Eclipse die hashCode() – und equals() – Methode dazugenerieren zu lassen. Klingt doch nach einem Heimspiel.

Hier also die erforderliche JPA-Entity:

package de.binaris.restletserver.model.entity;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
 
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Query;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* The JPA Entity class Users generated from the database within eclipse by File/New/Other/JPA/JPA Entities From Tables
*     Provides retrieval methods using NamedQueries for Users entities.
*    
*     (Implementation of the ‚TablePerClass‘ Design Pattern.)
*
* @author krull
*/
@Entity
@Table(name=“users“,
       catalog=“users_db“)
@NamedQueries({
   @NamedQuery(name = „Users.findAll“, query = „SELECT u FROM Users u“),
   @NamedQuery(name = „Users.findById“, query = „SELECT u FROM Users u WHERE u.iduser = :id“),
   @NamedQuery(name = „Users.findByUsername“, query = „SELECT u FROM Users u WHERE u.username = :username“),
   @NamedQuery(name = „Users.findByPassword“, query = „SELECT u FROM Users u WHERE u.password = :password“),
   @NamedQuery(name = „Users.findByUserID“, query = „SELECT u FROM Users u WHERE u.userID = :userID“),
   @NamedQuery(name = „Users.findByKnr“, query = „SELECT u FROM Users u WHERE u.knr = :knr“),
   @NamedQuery(name = „Users.findByEmail“, query = „SELECT u FROM Users u WHERE u.email = :email“),
   @NamedQuery(name = „Users.findByCreationDate“, query = „SELECT u FROM Users u WHERE u.creationDate = :creationDate“),
   @NamedQuery(name = „Users.findByDescription“, query = „SELECT u FROM Users u WHERE u.description = :description“)}
)
@SuppressWarnings({„rawtypes“, „unchecked“})
public class Users implements Serializable {
     
   public static final String USERS_FIND_ALL               = „Users.findAll“;
   public static final String USERS_FIND_BY_ID             = „Users.findById“;
   public static final String USERS_FIND_BY_USERNAME       = „Users.findByUsername“;
   public static final String USERS_FIND_BY_PASSWORD       = „Users.findByPassword“;
   public static final String USERS_FIND_BY_USERID         = „Users.findByUserID“;
   public static final String USERS_FIND_BY_KNR             = „Users.findByKnr“;
   public static final String USERS_FIND_BY_EMAIL           = „Users.findByEmail“;
   public static final String USERS_FIND_BY_CREATION_DATE   = „Users.findByCreationDate“;
   public static final String USERS_FIND_BY_DESCRIPTION     = „Users.findByDescription“;
 
      private static final long serialVersionUID = 7215275413679629379L;
 
      @Id
      @GeneratedValue
      @Basic(optional = false)
      @Column(name = „iduser“)
      private Integer iduser;
 
      @Column(name = „username“)
      private String username;
     
      @Column(name = „password“)
      private String password;
     
      @Column(name = „userID“)
      private String userID;
     
      @Basic(optional = false)
      @Column(name = „knr“)
      private Integer knr;
     
      @Column(name = „creationDate“)
      @Temporal(TemporalType.TIMESTAMP)
      private Date creationDate;
 
      @Column(name = „description“)
      private String description;
     
      @Basic(optional = false)
      @Column(name = „email“)
      private String email;
  
      public Users() {
      }
 
      public Users(Integer iduser) {
           this.iduser = iduser;
      }
  
      public Users(Integer iduser, String username, String password,
                 String userID, Integer knr, Date creationDate,
                 String description, String email) {
            this.iduser       = iduser;
            this.username     = username;
            this.password     = password;
            this.userID       = userID;
            this.knr           = knr;
            this.creationDate = creationDate;
            this.description   = description;
            this.email         = email;
      }
  
      public Integer getIduser() {
            return this.iduser;
      }
 
      public void setIduser(Integer iduser) {
            this.iduser = iduser;
      }
 
      public Date getCreationDate() {
            return this.creationDate;
      }
 
      public void setCreationDate(Date creationDate) {
            this.creationDate = creationDate;
      }
 
      public Integer getKnr() {
            return this.knr;
      }
 
      public void setKnr(Integer knr) {
            this.knr = knr;
      }
 
      public String getPassword() {
            return this.password;
      }
 
      public void setPassword(String password) {
            this.password = password;
      }
 
      public String getUserID() {
            return this.userID;
      }
 
      public void setUserID(String userID) {
            this.userID = userID;
      }
 
      public String getUsername() {
            return this.username;
      }

      public void setUsername(String username) {
            this.username = username;
      }
 
      public String getDescription() {
            return this.description;
      }
 
      public void setDescription(String description) {
            this.description = description;
      }
 
      public String getEmail() {
            return this.email;
      }
     
      public void setEmail(String email) {
            this.email = email;
      }
     
      @Override
      public int hashCode() {
           return iduser != null ? iduser.hashCode() :  
             System.identityHashCode(this);
      }
 
      @Override
      public boolean equals(Object object) {
       if (!(object instanceof Users)) {
           return false;
       }
       Users castOther = (Users) object;
       return iduser != null ? iduser.equals(castOther.getIduser())  
               false;
      }
 
      /**
      * toString
      * @return String
      */
      @Override
      public String toString() {
           StringBuilder builder = new StringBuilder();       builder.append(„Users“).append(„@“).append(System.identityHashCode(this)).append(“ [„);
       builder.append(„iduser“).append(„='“).append(this.iduser).append(„‚ „);
       builder.append(„username“).append(„='“).append(this.username).append(„‚ „);
       builder.append(„password“).append(„='“).append(this.password).append(„‚ „);
       builder.append(„userID“).append(„='“).append(this.userID).append(„‚ „);
       builder.append(„knr“).append(„='“).append(this.knr).append(„‚ „);
       builder.append(„creationDate“).append(„='“).append(this.creationDate).append(„‚ „);      
       builder.append(„description“).append(„='“).append(this.description).append(„‚ „);      
       builder.append(„email“).append(„='“).append(this.email).append(„‚ „);      
       builder.append(„]“);
 
       return builder.toString();
      }
 
      /**
      * toJson
      * @return String
      */
      public String toJson() {
           StringBuilder builder = new StringBuilder();
    
     builder.append(„{“ + ‚“‚ + „Users“ + ‚“‚ + „:“);
     builder.append(„{„);
     builder.append(‚“‚ + „iduser“ + ‚“‚).append(„:“).append(‚“‚).append(this.iduser).append(‚“‚).append(„, „);
     builder.append(‚“‚ + „username“ + ‚“‚).append(„:“).append(‚“‚).append(this.username).append(‚“‚).append(„, „);
     builder.append(‚“‚ + „password“ + ‚“‚).append(„:“).append(‚“‚).append(this.password).append(‚“‚).append(„, „);
     builder.append(‚“‚ + „userID“ + ‚“‚).append(„:“).append(‚“‚).append(this.userID).append(‚“‚).append(„, „);
     builder.append(‚“‚ + „knr“ + ‚“‚).append(„:“).append(‚“‚).append(this.knr).append(‚“‚).append(„, „);
     builder.append(‚“‚ + „creationDate“ + ‚“‚).append(„:“).append(‚“‚).append(this.creationDate).append(‚“‚).append(„, „);
     builder.append(‚“‚ + „email“ + ‚“‚).append(„:“).append(‚“‚).append(this.email).append(‚“‚);
     builder.append(„}“);
     builder.append(„}“);
    
     return builder.toString();
   }
  
      /**
      * toXml
      *
      * @return xml String
      */
      public String toXml() {
           StringBuilder builder = new StringBuilder();
    
     builder.append(„<Users>“);
     builder.append(„<iduser>“).append(this.iduser).append(„</iduser>“);
     builder.append(„<username>“).append(this.username).append(„</username>“);
     builder.append(„<password>“).append(this.password).append(„</password>“);
     builder.append(„<userID>“).append(this.userID).append(„</userID>“);
     builder.append(„<knr>“).append(this.knr).append(„</knr>“);
     builder.append(„<creationDate>“).append(this.creationDate).append(„</creationDate>“);      
     builder.append(„<description>“).append(this.description).append(„</description>“);      
     builder.append(„<email>“).append(this.email).append(„</email>“);        
     builder.append(„</Users>“);
    
     return builder.toString();
   }
  
   // NamedQuery retrieval methods:
      public static List<Users> findAll(final EntityManager em) {
       final Query query = em.createNamedQuery(USERS_FIND_ALL);
        return query.getResultList();
      }
 
      public static Users findById(final Integer id, final EntityManager em) {
       final Query query = em.createNamedQuery(USERS_FIND_BY_ID);
       query.setParameter(„id“, id);
       final List list = query.getResultList();
       if (list == null || list.isEmpty()) {
           return null;
       }
       return (Users)list.get(0);
      }
 
      public static Users findByUsername(final String username, final EntityManager em) {
       final Query query = em.createNamedQuery(USERS_FIND_BY_USERNAME);
       query.setParameter(„username“, username);
       final List list = query.getResultList();
       if (list == null || list.isEmpty()) {
           return null;
       }
       return (Users)list.get(0);
      }
 
      public static Users findByDescription(final String description, final EntityManager em) {
      final Query query = em.createNamedQuery(USERS_FIND_BY_DESCRIPTION);
      query.setParameter(„description“, description);
      final List list = query.getResultList();
      if (list == null || list.isEmpty()) {
           return null;
      }
      return (Users)list.get(0);
      }
  
      public static Users findByPassword(final String password, final EntityManager em) {
      final Query query = em.createNamedQuery(USERS_FIND_BY_PASSWORD);
      query.setParameter(„password“, password);
      final List list = query.getResultList();
      if (list == null || list.isEmpty()) {
           return null;
      }
      return (Users)list.get(0);
      }
  
      public static List<Users> findByUserID(final String userID, final EntityManager em) {
      final Query query = em.createNamedQuery(USERS_FIND_BY_USERID);
      query.setParameter(„userID“, userID);
      return query.getResultList();
//         final List list = query.getResultList();
//         if (list == null || list.isEmpty()) {
//               return null;
//         }
//         return (Users)list.get(0);
    }
  
      public static List<Users> findByKnr(final Integer knr, final EntityManager em) {
      final Query query = em.createNamedQuery(USERS_FIND_BY_KNR);
      query.setParameter(„knr“, knr);
      return query.getResultList();
    }
  
      public static List<Users> findByCreationDate(final Date creationDate, final EntityManager em) {
       final Query query = em.createNamedQuery(USERS_FIND_BY_CREATION_DATE);
       query.setParameter(„creationDate“, creationDate);
       return query.getResultList();
    }
  
      public static Users findByEmail(final String email, final EntityManager em) {
      final Query query = em.createNamedQuery(USERS_FIND_BY_EMAIL);
      query.setParameter(„email“, email);
      final List list = query.getResultList();
      if (list == null || list.isEmpty()) {
           return null;
      }
      return (Users)list.get(0);
    }
}

Daraus legt man sich im JBoss Developer Studio die Seam Entity (mit UsersHome, und UsersList) an und bekommt zu diesen die entsprechenden XHTML-Views für die Users Entity gleich mitgeliefert, die man dann genau wie die Seam Entities weiterentwickeln und ändern kann.

–       UsersHome extends EntityHome<Users>
und wird hier bevorzugt als EntityManagerFactory verwendet:

UsersHome userHome = new UsersHome();
EntityManager em = userHome.getEntityManager();
UsersDto userDto = new UsersDto(
(Integer)userHome.getId(), „binaris“, „binaris“, knr.toString(), knr, date, description, email);
Users user = DtoConverter.getUsers(userDto);
em.persist(user);

–       UsersList extends EntityQuery<Users>
und wird hier verwendet, um mittels EJBQuery-Language die Liste aller vorhandenen
Users zu erhalten (hier besteht auch die Möglichkeit, erweiterte Queries auszuführen):

public UsersList() {
    setEjbql(select users from Users users);
}

Weiterhin kann man auch jederzeit eine neue Seam Form hinzufügen, z.B. die UserForm:

–       UsersForm extends EntityHome<Users> :
man kann also jede beliebige Form von EntityHome ableiten, wenn man für Datenbank-Zugriffe einen validen, transaktionsfähigen EntityManager braucht:

@Name(„usersForm“)
@SessionScoped
public class UsersForm extends EntityHome<Users>
{
// […]
}

Wie im Beispiel zu erkennen ist, wurden für die Verwendung der detachten Entities in JTA-Transaktionen (Request-basierte Transaktionen) DTOs, DtoConverter und eine DtoFactory verwendet, wie sie bereits im Blog-Eintrag hier zur Verwendung von GWT mit Hibernate beschrieben wurden.

Wie es bereits in diesem vorhandenen Blog-Eintrag hier beschrieben wurde, können dann beliebige Actions zusätzlich auf einer solchen Form-Bean implementiert werden, die dann über den Klick auf einen Link, oder einen Button oder andere Events aufgerufen werden können. Deshalb wird für die Admin GUI auch eine eigene RegisterUsersForm angelegt mit der registerUser() Action und folgender Signatur. Diese Form ist nur durch Users der Rolle ‘admin‘ aufrufbar:

@Name(„registerUsersForm“)
@Restrict(„#{s:hasRole(‚admin‘)}“)
public class RegisterUsersForm {
    public String registerUsers() {
    }
}

RESTlet-Framework auf dem JBoss Application Server

Das RESTlet Framework funktioniert nach dem Router-Prinzip, wie es auch in jeder web.xml nach der Servlet Spezifikation umgesetzt ist. Die benötigten Restlet JARs wurden bereits in einem vorhandenen Blog-Eintrag hier beschrieben. Aktiviert wird das RESTlet Servlet zusätzlich zum Seam Faces Servlet und zum Seam Resource Servlet per Restlet Servlet in der web.xml:

<?xml version=„1.0“ encoding=„UTF-8“?>

<web-app xmlns:xsi=„http://www.w3.org/2001/XMLSchema-instance“ xmlns=„http://java.sun.com/xml/ns/javaee“ xmlns:web=„http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd“ xsi:schemaLocation=„http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd“ id=„WebApp_ID“ version=„2.5“>

<display-name>binarisRestletServer</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>

<servlet>
   <servlet-name>RestletServlet</servlet-name>
   <servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
   <init-param>
     <param-name>org.restlet.application</param-name>
     <param-value>
de.binaris.restletserver.service.RestletServerApplication
</param-value>
   </init-param>
</servlet>
 
<servlet-mapping>
   <servlet-name>RestletServlet</servlet-name>
   <url-pattern>/restservice/*</url-pattern>
</servlet-mapping>
 
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.seam</url-pattern>
</servlet-mapping>
<context-param>
<param-name>org.jboss.jbossfaces.JSF_CONFIG_NAME</param-name>
<param-value>Mojarra-1.2</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.SKIN</param-name>
<param-value>blueSky</param-value>
</context-param>
<listener>
<listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
</listener>
<filter>
<filter-name>Seam Filter</filter-name>
<filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Seam Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>Seam Resource Servlet</servlet-name>
<servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Seam Resource Servlet</servlet-name>
<url-pattern>/seam/resource/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
</web-app>

Somit kann das Restlet Servlet Requests mit /restservice/* in der Uri weiterverarbeiten.

In der RestletServerApplication sind diese Pfade folgendermaßen hinterlegt:

import org.restlet.Application;
import org.restlet.Restlet;
import org.restlet.routing.Router;
import de.binaris.restletserver.resources.UserReaderByUserIdResource;
import de.binaris.restletserver.resources.UserWriterResource;
import de.binaris.restletserver.resources.UsersReaderByKnrResource;

/**
* The class for the RESTful Binaris Restlet Server application (router).

*
* @author krull
/
public class RestletServerApplication extends Application {

private static final String ROUTE_TO_PING           = „/ping“;

private static final String ROUTE_TO_USER_READER     = „/userreader“;

private static final String ROUTE_TO_USER_WRITER     = „/user“;

private static final String ROUTE_TO_USERS_READER   = „/usersreader“;

private static final Class<UserReaderByUserIdResource>

CLASS_USER_READER_RESOURCE = UserReaderByUserIdResource.class;

private static final Class<UserWriterResource>

CLASS_USER_WRITER_RESOURCE = UserWriterResource.class;

private static final Class<UsersReaderByKnrResource>

CLASS_USERS_READER_RESOURCE = UsersReaderByKnrResource.class;

/**
* Creates a root Restlet that will receive all incoming webservice
*   http requests.
*
* return the Restlet router containing the attached routes
*/

@Override
public synchronized Restlet createInboundRoot() {

// Create a Restlet router, which routes each call to a new instance of the
//   matching resource.
Router router = new Router(getContext());

// Defines the ping route
router.attach(ROUTE_TO_PING, RestletServerPingResource.class);

// Defines the users C-R-U routes
router.attach(ROUTE_TO_USER_READER,     CLASS_USER_READER_RESOURCE);

router.attach(ROUTE_TO_USER_WRITER,     CLASS_USER_WRITER_RESOURCE);

router.attach(ROUTE_TO_USERS_READER,   CLASS_USERS_READER_RESOURCE);

return router;
}
}

Hier die UserReaderByUserIdResource.class:

 
package de.binaris.restletserver.resources;
 
import java.io.IOException;
 
import org.restlet.data.MediaType;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.Post;
 
import de.binaris.restletserver.businessobjects.UsersBO;
import de.binaris.restletserver.exceptions.InvalidJSONException;
import de.binaris.restletserver.service.representations.JsonRepresentation;
 
/**
* This REST Webservice Resource class has the single purpose
*   to find a User by its input JSON
*   responding to a RESTful HTTP Post request.
*
* @author krull
*/
public class UserReaderByUserIdResource extends RestrictPermissionsServerResource {
 
       @Post(„json“)
       public Representation postJSON() {
             StringRepresentation representation = null;
             try {
                    if (getRequest().getEntity() == null) {                    
                           representation = new StringRepresentation(UsersReturnCodesIF.USER_NOT_YET_REGISTERED_INVALID_JSON, MediaType.APPLICATION_JSON);
                    } else {
                           String json1 = UsersBO.getUsersDataRemoveJsonStringWrapper(getRequest().getEntity().getText());
                           final JsonRepresentation json = new JsonRepresentation(json1);
                          
                           String username = json.getJsonObject().getString(„user“);
                           String password = json.getJsonObject().getString(„password“);
                           if (!checkPermission(username, password)) {
                                  return new StringRepresentation(UsersReturnCodesIF.USER_REQUESTING_NO_PERMISSION, MediaType.APPLICATION_JSON);
                           }
                           String jsonStr = json.getText();
                           representation = new StringRepresentation(UsersBO.getUsersJsonByUserIdOrKnr(jsonStr), MediaType.APPLICATION_JSON);
                    }
             } catch (InvalidJSONException e) {
                    setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
                    representation = new StringRepresentation(UsersReturnCodesIF.USER_NOT_YET_REGISTERED_INVALID_JSON, MediaType.APPLICATION_JSON);
             } catch (IOException e) {
                    setStatus(Status.SERVER_ERROR_INTERNAL );
                    representation = new StringRepresentation(UsersReturnCodesIF.USER_NOT_YET_REGISTERED_DB_NOT_AVAILABLE, MediaType.APPLICATION_JSON);
             } catch (Throwable th) {
                    setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
                    representation = new StringRepresentation(UsersReturnCodesIF.USER_NOT_YET_REGISTERED_INVALID_JSON, MediaType.APPLICATION_JSON);
             }
             return representation;
       }
}

Hier die UsersReaderByKnrResource.class:

 
package de.binaris.restletserver.resources;
 
import java.io.IOException;
import org.restlet.data.MediaType;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.Post;
 
import de.binaris.restletserver.businessobjects.UsersBO;
import de.binaris.restletserver.exceptions.InvalidJSONException;
import de.binaris.restletserver.service.representations.JsonRepresentation;
 
/**
* This REST Webservice Resource class has the single purpose
*   to find a User by its input JSON
*     responding to a RESTful HTTP Post request.
*
* @author krull
*/
public class UsersReaderByKnrResource extends RestrictPermissionsServerResource {
 
       @Post(„json“)
       public Representation postJSON() {
             StringRepresentation representation = null;
             try {
                    if (getRequest().getEntity() == null) {
                           representation = new StringRepresentation(UsersReturnCodesIF.USER_NOT_YET_REGISTERED_INVALID_JSON, MediaType.APPLICATION_JSON);
                    } else {
                           String json1 = UsersBO.getUsersDataRemoveJsonStringWrapper(getRequest().getEntity().getText());
                           final JsonRepresentation json = new JsonRepresentation(json1);
                          
                           String username = json.getJsonObject().getString(„user“);
                           String password = json.getJsonObject().getString(„password“);
                           if (!checkPermission(username, password)) {
                                  return new StringRepresentation(UsersReturnCodesIF.USER_REQUESTING_NO_PERMISSION, MediaType.APPLICATION_JSON);
                           }
                           String jsonStr = json.getText();
                           representation = new StringRepresentation(UsersBO.getUsersJsonByUserIdOrKnr(jsonStr), MediaType.APPLICATION_JSON);
                    }
             } catch (InvalidJSONException e) {
                    setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
                    representation = new StringRepresentation(UsersReturnCodesIF.USER_NOT_YET_REGISTERED_INVALID_JSON, MediaType.APPLICATION_JSON);
             } catch (IOException e) {
                    setStatus(Status.SERVER_ERROR_INTERNAL );
                    representation = new StringRepresentation(UsersReturnCodesIF.USER_NOT_YET_REGISTERED_DB_NOT_AVAILABLE, MediaType.APPLICATION_JSON);
             } catch (Throwable th) {
                    setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
                    representation = new StringRepresentation(UsersReturnCodesIF.USER_NOT_YET_REGISTERED_INVALID_JSON, MediaType.APPLICATION_JSON);
             }
             return representation;
       }
}

Hier die UserWriterResource.class:

package de.binaris.restletserver.resources;
 
import java.io.IOException;
 
import org.restlet.data.MediaType;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.Post;
 
import de.binaris.restletserver.businessobjects.UsersBO;
import de.binaris.restletserver.exceptions.InvalidJSONException;
import de.binaris.restletserver.service.representations.JsonRepresentation;
 
/**
* This REST Webservice Resource class has the single purpose
*   to saveOrUpdate a User by its input JSON
*   responding to a RESTful HTTP Post request.
*
* @author krull
*/
public class UserWriterResource extends RestrictPermissionsServerResource {
 
       @Post
       public Representation saveOrUpdateUser(Representation entity) {
 
             StringRepresentation representation = null;
             try {
                    if (entity == null) {
                           representation = new StringRepresentation(UsersReturnCodesIF.USER_NOT_YET_REGISTERED_INVALID_JSON, MediaType.APPLICATION_JSON);
                    } else {
                           String json1 = UsersBO.getUsersDataRemoveJsonStringWrapper(getRequest().getEntity().getText());
                           final JsonRepresentation json = new JsonRepresentation(json1);
                          
                           String username = json.getJsonObject().getString(„user“);
                           String password = json.getJsonObject().getString(„password“);
                           if (!checkPermission(username, password)) {
                                  return new StringRepresentation(UsersReturnCodesIF.USER_REQUESTING_NO_PERMISSION, MediaType.APPLICATION_JSON);
                           }
                           String jsonStr = json.getText();
                           representation = new StringRepresentation(UsersBO.createOrUpdateByJson(jsonStr), MediaType.APPLICATION_JSON);
                    }
             } catch (InvalidJSONException e) {
                    setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
                    representation = new StringRepresentation(UsersReturnCodesIF.USER_NOT_YET_REGISTERED_INVALID_JSON, MediaType.APPLICATION_JSON);
             } catch (IOException e) {
                    setStatus(Status.SERVER_ERROR_INTERNAL );
                    representation = new StringRepresentation(UsersReturnCodesIF.USER_NOT_YET_REGISTERED_DB_NOT_AVAILABLE, MediaType.APPLICATION_JSON);
             } catch (Throwable th) {
                    representation = new StringRepresentation(UsersReturnCodesIF.USER_NOT_YET_REGISTERED_INVALID_JSON, MediaType.APPLICATION_JSON);
                    setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
             }
             return representation;
       }
}

Das BusinessObject für die Users “UsersBO.class“ sieht dann so aus:

package de.binaris.restletserver.businessobjects;
 
import java.util.List;
 
import org.apache.log4j.Logger;
 
import de.binaris.restletserver.domain.dto.DtoConverter;
import de.binaris.restletserver.domain.dto.DtoFactory;
import de.binaris.restletserver.domain.dto.UsersDto;
import de.binaris.restletserver.domain.dto.validation.UsersDtoValidator;
import de.binaris.restletserver.exceptions.InvalidJSONException;
import de.binaris.restletserver.exceptions.InvalidXMLException;
import de.binaris.restletserver.exceptions.UserAlreadyExistsException;
import de.binaris.restletserver.exceptions.UserNotFoundException;
import de.binaris.restletserver.model.entity.Users;
import de.binaris.restletserver.model.session.facade.UsersFacade;
import de.binaris.restletserver.model.session.facade.UsersFacadeIF;
import de.binaris.restletserver.resources.UsersReturnCodesIF;
import de.binaris.restletserver.utils.JSONUtil;
import de.binaris.restletserver.utils.XMLUtil;
 
/**
* The class for the JSON/XML input handling Business Objects of the Users entity.
*
* @author krull
*/
public class UsersBO {
      
   private static Logger log = Logger.getLogger(UsersBO.class);
      
       public UsersBO() {
       }
 
   /**
     * Creates new User entity or updates existing User entity
     *   by means of the input user XML representation.
     *     The User must not exist to save or update
     *     the User data, otherwise: throws UserAlreadyExistsException
     *
     * @param xml
    * @return the User dto as string
     * @throws InvalidXMLException
     * @throws UserAlreadyExistsException
     */
       public static String create(String xml)
       throws InvalidXMLException, UserAlreadyExistsException {
            
             UsersDto userDto = XMLUtil.getUsersDtoFromXML(xml);
             if (userDto != null) {
                    // Check if user exists: if not, create User else, throw Exception
                    UsersFacadeIF facade = new UsersFacade();
                    if (facade.findByUserID(userDto.getUserID()) == null) {
                           // Facade insert
                           facade.saveOrUpdateUser(DtoConverter.getUsers(userDto));
                           return userDto.toXml();
                    } else {
                           throw new UserAlreadyExistsException();
                    }
             } else {
                    throw new InvalidXMLException();
             }
       }
 
   /**
     * Creates new User entity or updates existing User
   *   entity by means of the input User json.
     *        
     * @param json
     * @return the return code for the registered User
     * @throws InvalidJSONException
     * @see de.binaris.restletserver.resources.json.messages.returncodes.UsersReturnCodesIF
     */
       public static String createOrUpdateByJson(String json) throws InvalidJSONException {
            
             UsersDto userDto = JSONUtil.getUsersDtoFromJSON(json);
             if (userDto != null) {
                    // Check if user exists: if not, create User else: throw Exception
                    // Facade findByUsername
                    UsersFacadeIF facadeUser = new UsersFacade();
                    List<Users> users = facadeUser.findByUserID(userDto.getUserID());
                    if (users != null && !users.isEmpty()) {
                           log.info(„usersFound: “ + users.toString());
                           Users userFound = users.get(0);
                           if (userFound != null) {
                                  log.info(„userFound: “ + userFound.toString());
                                  Users updatedUsers = DtoConverter.getUsers(userDto);
                                  updatedUsers.setIduser(userFound.getIduser());
                                  if (UsersDtoValidator.isValidUsersDto(userDto)) {
                                     facadeUser.saveOrUpdateUser(updatedUsers);
                                     log.info(„user updated: “ + updatedUsers.toString());
                                  } else {
                                        log.info(„user not inserted, invalid user attributes: “ + userDto.toString());
                                        return UsersReturnCodesIF.USER_NOT_YET_REGISTERED_INVALID_USERS_ATTRIBUTES;
                                  }
                           }
                    } else {
                           log.info(„user not found.“);
                           if (UsersDtoValidator.isValidUsersDto(userDto)) {
                                  facadeUser.saveOrUpdateUser(DtoConverter.getUsers(userDto));
                                  log.info(„user inserted: “ + userDto.toString());
                           } else {
                                  log.info(„user not inserted, invalid user attributes: “ + userDto.toString());
                                  return UsersReturnCodesIF.USER_NOT_YET_REGISTERED_INVALID_USERS_ATTRIBUTES;
                           }
                    }
                    return UsersReturnCodesIF.USER_HAS_BEEN_REGISTERED;
             } else {
                    return UsersReturnCodesIF.USER_NOT_YET_REGISTERED_INVALID_JSON;
             }
       }
      
   /**
     * Retrieval method to get the json representation
     *   of the input User found by its input json
     *   providing attributes like userID et al.
     *        
     * @param json
     * @return the return code for the registered User
     * @throws InvalidJSONException
     * @see de.binaris.restletserver.resources.json.messages.returncodes.UsersReturnCodesIF
     */
       public static String getUsersJsonByUserIdOrKnr(String json) throws InvalidJSONException {
            
             UsersDto userDto = JSONUtil.getUsersDtoFromJSON(json);
             if (userDto != null) {
                    // Check if user exists: if not, create User, else: throw exception
                    // Facade findByUsername
                    UsersFacadeIF facadeUser = new UsersFacade();
                    List<Users> users = facadeUser.findByUserID(userDto.getUserID());
                    if (users != null && !users.isEmpty() && users.get(0) != null) {
                           log.info(„usersFound: “ + users.toString());
                           Users userFound = users.get(0);
                           log.info(„userFound: “ + userFound.toString());
                           return UsersReturnCodesIF.USER_HAS_BEEN_REGISTERED;
                    } else {
                           users = facadeUser.findByKnr(userDto.getKnr());
                           if (users != null && !users.isEmpty() && users.get(0) != null) {
                                  log.info(„usersFound: “ + users.toString());
                                  Users userFound = users.get(0);
                                  log.info(„userFound: “ + userFound.toString());
                                  return UsersReturnCodesIF.USER_HAS_NOT_BEEN_REGISTERED_SINCE_NOT_REQUESTED_KNR_EXISTS;
                           } else {
                                  log.info(„User not found.“);
                                  return UsersReturnCodesIF.USER_HAS_NOT_BEEN_REGISTERED_SINCE_NOT_REQUESTED;
                           }
                    }
             } else {
                    return UsersReturnCodesIF.USER_NOT_YET_REGISTERED_INVALID_JSON;
             }
       }
      
   /**
     * Retrieval method to get the xml representation of all Users found.
     *
     * @return xml string of the found Users
     */
       public static String getAllXml() {
             StringBuilder usersBuilder = new StringBuilder();
             usersBuilder.append(„<Users-result>“);
 
             UsersFacadeIF facade = new UsersFacade();
             List<UsersDto> result = DtoFactory.getUserDtos(facade.findAll().toString());
             usersBuilder.append(„<count>“).append(result.size()).append(„</count>“);
             for (UsersDto dto : result) {
                    usersBuilder.append(dto.toXml());
             }
             usersBuilder.append(„</Users-result>“);
             return usersBuilder.toString();
       }
 
   /**
     * Retrieval method to get the json representation of all Users found.
     *
     * @return json string of the found Users
     */
       public static String getAllJson() {
             StringBuilder usersBuilder = new StringBuilder();
             UsersFacadeIF facade = new UsersFacade();
             List<UsersDto> result = DtoFactory.getUserDtos(facade.findAll().toString());
 
             usersBuilder.append(„{\“Users-result\“:{\“count\“:\““).append(result.size()).append(„\“, \“Users-all\“:[„);
             for (UsersDto dto : result) {
                    usersBuilder.append(dto.toJson());
                    usersBuilder.append(„,“);
             }
             String ret = usersBuilder.toString();
             int len = ret.length() – 1;
             ret = ret.substring(0, len) + „]}}“;
             return ret;
       }
 
   /**
   * Retrieval method to get the xml representation of the User
     *   found by its input userID.
     *
     * @param userID
     * @return xml string of the found User or matching
     *         return code from UsersReturnCodesIF
     * @see de.binaris.restletserver.resources.json.messages.returncodes.UsersReturnCodesIF
     */
       public static String getXmlByUserId(String userID) {
             try {
                    UsersFacadeIF facadeUsers = new UsersFacade();
                    List<Users> list = facadeUsers.findByUserID(userID);
                    log.info(„list: “ + list);
                    log.info(„userID: “ + userID);
                    return (list != null && !list.isEmpty()) ? list.get(0).toXml() : null;
             } catch (ExceptionInInitializerError exError) {
           return UsersReturnCodesIF.USER_NOT_YET_REGISTERED_DB_NOT_AVAILABLE;              
             }
       }
      
   /**
     * Retrieval method to get the json representation of the User found by its input userID.
     *
     * @param userID
     * @return json string of the found User or matching return code from UsersReturnCodesIF
     * @see de.binaris.restletserver.resources.json.messages.returncodes.UsersReturnCodesIF
     */
       public static String getJsonByUserId(String userID) {
             try {
                    UsersFacadeIF facadeUsers = new UsersFacade();
                    List<Users> list = facadeUsers.findByUserID(userID);
                    log.info(„list: “ + list);
                    log.info(„userID: “ + userID);
                    return (list != null && !list.isEmpty()) ? list.get(0).toJson() : null;
             } catch (ExceptionInInitializerError exError) {
           return UsersReturnCodesIF.USER_NOT_YET_REGISTERED_DB_NOT_AVAILABLE;              
             }
       }
      
   /**
     * Retrieval method to get the xml representation of the User found by its input customer number (knr).
     *
     * @param userID
     * @return xml string of the found User or matching return code from UsersReturnCodesIF
     * @see de.binaris.restletserver.resources.json.messages.returncodes.UsersReturnCodesIF
     */
       public static String getXmlByKnr(String knr) {
             try {
                    UsersFacadeIF facadeUsers = new UsersFacade();
                    List<Users> list = facadeUsers.findByKnr(Integer.parseInt(knr));
                    log.info(„Users: “ + list);
                    log.info(„knr: “ + knr);
                    return (list != null) ? list.get(0).toXml() : null;
             } catch (ExceptionInInitializerError exError) {
           return UsersReturnCodesIF.USER_NOT_YET_REGISTERED_DB_NOT_AVAILABLE;              
             }
       }
 
   /**
     * Retrieval method to get the json representation of the User found by its input customer number (knr).
     *
     * @param userID
     * @return json string of the found User or matching return code from UsersReturnCodesIF
     * @see de.binaris.restletserver.resources.json.messages.returncodes.UsersReturnCodesIF
     */
       public static String getJsonByKnr(String knr) {
             try {
                    UsersFacadeIF facadeUsers = new UsersFacade();
                    List<Users> list = facadeUsers.findByKnr(Integer.parseInt(knr));
                    log.info(„Users: “ + list);
                    log.info(„knr: “ + knr);
                    return (list != null) ? list.get(0).toJson() : null;
             } catch (ExceptionInInitializerError exError) {
           return UsersReturnCodesIF.USER_NOT_YET_REGISTERED_DB_NOT_AVAILABLE;              
             }
       }
 
       /**
     * Retrieval method to get the xml representation of the User found by its input email address (email).
     *
     * @param email
     * @return xml string of the found User or matching return code from UsersReturnCodesIF
   * @see de.binaris.restletserver.resources.json.messages.returncodes.UsersReturnCodesIF
     */
       public static String getXmlByEmail(String email) {
             try {
                    UsersFacadeIF facadeUsers = new UsersFacade();
                    List<Users> list = facadeUsers.findByEmail(email);
                    log.info(„Users: “ + list);
                    log.info(„email: “ + email);
                    return (list != null) ? list.get(0).toXml() : null;
             } catch (ExceptionInInitializerError exError) {
                    return UsersReturnCodesIF.USER_NOT_YET_REGISTERED_DB_NOT_AVAILABLE;                    
             }
       }
      
       /**
     * Retrieval method to get the json representation of the User found by its input email address (email).
     *
     * @param email
     * @return json string of the found User or matching return code from UsersReturnCodesIF
     * @see de.binaris.restletserver.resources.json.messages.returncodes.UsersReturnCodesIF
     */
       public static String getJsonByEmail(String email) {
             try {
                    UsersFacadeIF facadeUsers = new UsersFacade();
                    List<Users> list = facadeUsers.findByEmail(email);
                    log.info(„Users: “ + list);
                    log.info(„email: “ + email);
                    return (list != null) ? list.get(0).toJson() : null;
             } catch (ExceptionInInitializerError exError) {
                    return UsersReturnCodesIF.USER_NOT_YET_REGISTERED_DB_NOT_AVAILABLE;                    
             }
       }
      
   /**
     * Updates (User found) or inserts (User not found) the User entity of the input User json.
     *
     * @param json
     * @return the updated User json
     */
       public static String update(String xml) throws InvalidXMLException, UserNotFoundException {
            
             UsersDto userDto = XMLUtil.getUsersDtoFromXML(xml);
             if (userDto != null) {
                    // Check if user exists: update, else: throw Exception
                    UsersFacadeIF facade = new UsersFacade();
                    UsersDto tmpUser = (DtoFactory.getUserDtos(facade.findByUserID(userDto.getUserID()).toString())).get(0);
                    if (tmpUser != null) {
                           // only update: the password
                           tmpUser.setPassword(userDto.getPassword());
                           // Facade update (tmpUser)
                           facade.saveOrUpdateUser(DtoConverter.getUsers(tmpUser));
                           return tmpUser.toXml();
                    } else {
                           // Facade save (tmpUser)
                           facade.saveOrUpdateUser(DtoConverter.getUsers(userDto));
                           return userDto.toXml();
                    }
             } else {
                    throw new InvalidXMLException();
             }
       }
      
       /**
     * Convenience method to preformat the input json1 by removing the outer json format brackets
     *
     * @param json1
     * @return json
     */
       public static String getUsersDataRemoveJsonStringWrapper(String json1) {
             String[] licenseData = json1.split(„users“);
             if (licenseData != null && licenseData.length > 1) {
                    int start = licenseData[1].trim().indexOf(„:“) + 1;
                    int end   = licenseData[1].trim().length() – 1;
                    json1 = licenseData[1].trim().substring(start, end);
             }
             return json1;
       }
}
 

Für die Persistenz der per REST-Request angefragten oder gesendeten Daten wird eine Hibernate-Facade verwendet, die zusammen mit ihrer Basis-Klasse das folgende UsersFacadeIF – Interface implementiert:

package de.binaris.restletserver.model.session.facade;
 
import java.util.Date;
import java.util.List;
 
import org.hibernate.Session;
import org.hibernate.StaleObjectStateException;
 
import de.binaris.restletserver.model.entity.Users;
 
/**
* The interface for the UsersFacade
*
* @author krull
*/
public interface UsersFacadeIF {
      
   /**
     *
     * @return the current HibernateSession
     */     
   public abstract Session getSession();
 
   /**
     * This saveOrUpdate method saves or updates Users by the given user.
     *
     * @param user
     */
   public void saveOrUpdateUser(Users user) throws StaleObjectStateException;
      
   /**
     * This finder method finds Users by knr of the given Users.
     *
     * @param knr
     * @return the found Users
     */
   public abstract List<Users> findByKnr(final Integer knr);
 
   /**
     * This finder method finds Users by email of the given Users.
     *
     * @param email
     * @return the found Users
     */
   public abstract List<Users> findByEmail(final String email);
      
   /**
     * This finder method finds Users by userID of the given Users.
     *
     * @param userID
     * @return the found Users
     */
     public abstract List<Users> findByUserID(final String userID);
      
   /**
     * This finder method finds Users by description of the given Users.
     *
     * @param description
     * @return the found Users
     */
     public abstract List<Users> findByDescription(final String description);
      
   /**
     * This finder method finds Users by the given creationDate.
     *
     * @param creationDate
     * @return the list of found Users
     */
     public abstract List<Users> findByCreationDate(final Date creationDate);
      
   /**
     * This finder method finds number of Users.
     *
     * @return number of all Users
     */
     public abstract int countAllUsers();
 
   /**
     * This finder method finds the list of all Users.
     *
     * @return the list of all Users
     */
     public abstract List<Users> findAll();
 
   /**
     * This getter method returns the list of all Customers.
     *
     * @return the list of all Customers
     */
     public abstract List<Users> getAll();
}
 

Hier dieUsersFacade.class:

package de.binaris.restletserver.model.session.facade;
 
import org.hibernate.Session;
import de.binaris.restletserver.dao.DaoBeanFactory;
import de.binaris.restletserver.dao.UsersDao;
/**
* The Users facade for retrieval of Users by means of UsersDao
*
* @author krull
*/
public class UsersFacade extends UsersFacadeBase {
 
       private UsersDao<?, ?> usersDao = null;
      
       /**
       * the no-args constructor
     */
       public UsersFacade() {
             super();           
             DaoBeanFactory.getFacadeSessionFactory();
             usersDao = DaoBeanFactory.createUsersDao();
             super.setUsersDao(usersDao);
   }
 
       /**
       * @return session the session to get
     */
       @Override
       public Session getSession() {
             return usersDao.getFactory().getCurrentSession();
       }
}

Hier die Basis-Klasse UsersFacadeBase:

package de.binaris.restletserver.model.session.facade;

import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.StaleObjectStateException;
import org.hibernate.criterion.Projections;

import de.binaris.restletserver.dao.UsersDao;
import de.binaris.restletserver.model.entity.Users;

/**
* The UsersFacadeBase for retrieval of Users by means of UsersDao
*
* @author krull
*/
public abstract class UsersFacadeBase implements UsersFacadeIF {
      
       private static Logger log = Logger.getLogger(UsersFacadeBase.class);
      
       private UsersDao<?, ?> usersDao;
 
       /**
       * The no-args constructor.
      */
       public UsersFacadeBase() {
       }
      
       /**
       * The UsersDao related constructor.
       *
       * @param usersDao the UsersDao to be used and set
      */
       public UsersFacadeBase(UsersDao<?, ?> usersDao) {
             this.usersDao = usersDao;
   }
 
       /**
       * @param usersDao the UsersDao to set
      */
       public void setUsersDao(UsersDao<?, ?> usersDao) {
             this.usersDao = usersDao;
       }
 
       /**
       * The base class declaration method to be overriden by subclasses.
       *
       * @return session the session to get
      */
       public abstract Session getSession();
 
       /**
       *
      * @see de.binaris.restletserver.model.session.facade.UsersFacadeIF#saveOrUpdateUser(de.binaris.restletserver.model.entity.Users)
      */
       public void saveOrUpdateUser(Users user) throws StaleObjectStateException {
             try {
                    getSession().beginTransaction();
                    usersDao.saveOrUpdate(user);
                    getSession().getTransaction().commit();
             } catch (StaleObjectStateException e) {
                    try {
                           getSession().getTransaction().rollback();
                    } catch (HibernateException e1) {
                           log.error(„Error rolling back transaction in UsersFacadeBase.saveOrUpdateUser“);
                    }
                    throw e;
             }
       }
      
       /**
       * This finder method retrieves the list of all Users.
       *
       * @return the list of all Users
     * @see see de.binaris.restletserver.model.session.facade.UsersFacadeIF#findAll()
     */
       @SuppressWarnings(„unchecked“)
       public List<Users> findAll() {
             getSession().beginTransaction();
             List<Users> list = (List<Users>)usersDao.findAll();
             getSession().getTransaction().commit();
             return list;
       }
 
       /**
       * This finder method finds Users by the given userID.
       *
       * @param userID
       * @return the list of found Users
     * @see de.binaris.restletserver.model.session.facade.UsersFacadeIF#findByUserID()
       */
       public List<Users> findByUserID(final String userID) {
             getSession().beginTransaction();
             List<Users> list = (List<Users>)usersDao.findByUserID(userID);
             getSession().getTransaction().commit();
             log.info(„userID: “ + userID + “ result: “ + list);
             return list;
       }
      
       /**
       * This finder method finds Users by the given description.
       *
       * @param description
       * @return the list of found Users
       * @see de.binaris.restletserver.model.session.facade.UsersFacadeIF#findByDescription()
       */
       public List<Users> findByDescription(final String description) {
             getSession().beginTransaction();
             List<Users> list = (List<Users>)usersDao.findByDescription(description);
             getSession().getTransaction().commit();
             log.info(„description: “ + description + “ result: “ + list);
             return list;
       }
      
       /**
       * This finder method finds Users by the given email.
       *
       * @param email
       * @return the list of found Users
       * @see de.binaris.restletserver.model.session.facade.UsersFacadeIF#findByEmail()
       */
       public List<Users> findByEmail(final String email) {
             getSession().beginTransaction();
             List<Users> list = (List<Users>)usersDao.findByEmail(email);
             getSession().getTransaction().commit();
             log.info(„email: “ + email + “ result: “ + list);
             return list;
       }
      
       /**
     * This finder method finds Users by knr of the given Users.
     *
     * @param knr
       * @return the list of found Users
     * @see de.binaris.restletserver.model.session.facade.UsersFacadeIF#findByKnr()
     */
       public List<Users> findByKnr(final Integer knr) {
             getSession().beginTransaction();
             List<Users> list = (List<Users>)usersDao.findByKnr(knr);
             getSession().getTransaction().commit();
             return list;
       }
 
       /**
     * This finder method finds Users by the given creationDate.
     *
    * @param creationDate
       * @return the list of found Users
     * @see de.binaris.restletserver.model.session.facade.UsersFacadeIF#findByCreationDate()
     */
       public List<Users> findByCreationDate(final Date creationDate) {
             getSession().beginTransaction();
             List<Users> list = (List<Users>)usersDao.findByCreationDate(creationDate);
             getSession().getTransaction().commit();
             return list;
       }
      
       /**
     * This finder method finds number of Users.
       *
     * @see de.binaris.restletserver.model.session.facade.UsersFacadeIF#countAllUsers()
     */
       public int countAllUsers() {
             int result = 0;
             getSession().beginTransaction();
             result = ((Integer) getSession().createCriteria(Users.class)
                                                  .setProjection(Projections.rowCount())
                                                  .uniqueResult())
                                                  .intValue();
             getSession().getTransaction().commit();
             return result;
       }
 
       /**
       *
     * @see de.binaris.restletserver.model.session.facade.UsersFacadeIF#getAll()
     */
       public List<Users> getAll() {
             return findAll();
       }
      
       /**
       * The main method for a quick test
       *
       * @param args
       */
       public static void main(String[] args) {
       }
}
 

Die Klasse UsersFacadeBase verwendet wiederum die bereits aus früheren Blog-Einträgen hier und hier bekannten Hibernate-Klassen: DaoBeanFactory, DaoCrudBase, DaoCrudBaseIF, HibernateSessionFactory, SessionFactoryConfigIF und den hier benötigten Hibernate UsersDao.
Die hibernate.cfg.xml sieht folgendermaßen aus:

<!DOCTYPE hibernate-configuration PUBLIC
„-//Hibernate/Hibernate Configuration DTD 3.0//EN“
„http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd“>
<hibernate-configuration>
<session-factory>
<property name=„connection.url“>jdbc:mysql://localhost:3306/users_db?useUnicode=true&amp;characterEncoding=UTF-8</property>
<property name=„connection.username“>root</property>
<property name=„connection.password“>router</property>
<property name=„connection.driver_class“>com.mysql.jdbc.Driver</property>
<property name=„dialect“>org.hibernate.dialect.MySQLDialect
</property>
<property name=„current_session_context_class“>thread</property>
<property name=„hibernate.transaction.factory_class“>org.hibernate.transaction.JDBCTransactionFactory
</property>
<property name=„hbm2ddl.auto“>update
</property>
<mapping class=„de.binaris.restletserver.model.entity.Users“ />
</session-factory>
</hibernate-configuration>

Eine evtl. Migration auf den JBoss 7 mit Hibernate 4 und einem JDBC 4 entsprechenden Datenbank-Treiber ist bereits in einem vorhandenen Blog-Eintrag hier beschrieben, dann müsste auch die .dtd-Deklaration migriert werden, wie auf jboss.org beschrieben ist.

Die persistence.xml für das Beispiel sieht folgendermaßen aus und befindet sich im META-INF:

<?xml version=„1.0“ encoding=„UTF-8“?>
<!– Persistence deployment descriptor for dev profile –>
<persistence 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_1_0.xsd“ version=„1.0“>

<persistence-unit name=„binarisRestletServer“ transaction-type=„JTA“>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/binarisRestletServerDatasource</jta-data-source>
<properties>
<property name=„hibernate.dialect“
                 value=„org.hibernate.dialect.MySQLDialect“/>
<property name=„hibernate.hbm2ddl.auto“ value=„create-update“/>
<property name=„hibernate.show_sql“ value=„true“/>
<property name=„hibernate.format_sql“ value=„true“/>
<property name=„jboss.entity.manager.factory.jndi.name“
value=„java:/binarisRestletServerEntityManagerFactory“/>
</properties>
</persistence-unit>
</persistence>

Die binarisRestletServer-ds.xml sieht folgendermaßen aus und wird neben dem binarisRestletServer.war deployt (entweder im JBoss 6 Server/default/deploy-Verzeichnis oder im EAR-Archiv):

<?xml version=„1.0“ encoding=„UTF-8“?>
<datasources>
<local-tx-datasource>
<jndi-name>binarisRestletServerDatasource</jndi-name>
<use-java-context>true</use-java-context>
<connection-url>
jdbc:mysql://localhost:3306/users_db?useUnicode=true&amp;characterEncoding=UTF-8
</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>root</user-name>
<password>router</password>
<connection-property name=„autoReconnect“>true</connection-property>
</local-tx-datasource>
</datasources>

Wie man sieht, macht es viel Freude in relativ kurzer Zeit, RESTful-WebServices mit einem JSF-Web User Interface auf dem JBoss Application Server am Start zu haben, natürlich unter Verwendung des JBoss Seam Frameworks, jetzt Apache Delta Spike. Dabei können anstelle von EJBs auch ganz simple transaktionale Seam Entities mit JPA / Hibernate zum Einsatz kommen.

Wofür man eine solche User-Registrierung verwenden könnte, entzieht sich zwar meinem Vorstellungsvermögen, aber eine Erweiterung des Restlet-Servers auf einen Lizensierungs-Server, der per Secure REST-Aufruf überprüft, ob die Anzahl der erworbenen Unternehmens-Lizenzen für eine lizensierte App nicht überschritten wurde, oder der die Möglichkeit zur Lizensierung weiterer Android Devices bietet, könnte ich mir schon vorstellen.

Hier das Beispiel-Projekt zum Download in der JBoss 6.1 Version. Entpackt kann hieraus ganz schnell eine .WAR Datei exportiert werden, beim Deployment dann auch die Datei “binarisRestletServer-ds.xml“ ins Deployment-Verzeichnis des JBoss 6.1 / server/default/deploy mitdeployen. Hier das Deployment-Paket zum Deployment im genannten deploy-Verzeichnis des JBoss Application Servers 6.1.

Zum Abschluss hier noch der Hinweis auf das sehr gute Seminar zum Thema TDD mit Java von Binaris
hier und hier. Allen interessierten Leserinnen und Lesern noch eine angenehme Spätsommerzeit und einen schönen Herbstbeginn.

Kommentare

Ein Kommentar zu “Services – UserService mit JBoss RESTlet Server”

  1. Von WebApps – mit REST, JPA 2, EJB 3.2, Angular JS, JSF 2.2 auf JBoss WildFly 10 : Softwareentwicklung, Projektmanagement & Schulung | binaris informatik GmbH am Samstag, 30. Januar 2016 15:19

    […] einem RESTful WebService über entsprechende GET- oder POST-Http-Requests verfügbar gemacht, wie hier beispielhaft […]

Einen Kommentar hinzufügen...

Sie müssen registriert und angemeldet sein um einen Kommentar zu schreiben.