Wenn Sie EJB-Anwendungen (Enterprise JavaBeans) haben, die
über eine Sicht mit lokaler Schnittstelle bereitgestellt werden, können Sie
der Enterprise-Bean über Java™ API for RESTful Web Services (JAX-RS)
eine REST-konforme Schnittstelle bereitstellen.
Durch die Implementierung von Enterprise-Beans mit JAX-RS-Annotationen behalten Sie die
EJB-Funktionen bei, einschließlich Transaktionsunterstützung, Injektion von
Java-EE-Komponenten und -Ressourcen sowie
EJB-Session-Bean-Funktionen.
Vorbereitende Schritte
Bis EJB Version 3.1 benötigten Enterprise-Beans, die eine lokale EJB-Clientsicht erforderten,
auch eine separate Java-Schnittstelle. Diese Schnittstelle
war in der Regel in einer gesonderten Datei enthalten, in der die Methoden für die lokale
Sicht deklariert waren. Die Enterprise-Bean gibt an, dass die Schnittstelle für die lokale EJB-Sicht
mithilfe von Implementierungsdeskriptoren oder EJB-Annotationen implementiert wurde.
Wenn Sie die Spezifikation EJB 3.1 verwenden, haben Sie die Möglichkeit,
eine lokale Sicht einer Enterprise-Bean ohne einer expliziten lokalen EJB-Schnittstelle bereitzustellen.
Stattdessen hat die Enterprise-Bean eine Clientsicht ohne Schnittstelle, die auf den öffentlichen Methoden
Ihrer Beanklasse basiert.
Die Entwicklung von Enterprise-Beans mit einer Sicht ohne Schnittstelle kann aus den folgenden Gründen
einfacher sein als die Entwicklung von Enterprise-Beans mit einer lokalen Sicht:
- Enterprise-Beans mit einer Sicht ohne Schnittstelle erfordern keine separate Java-Schnittstellendeklaration.
- Enterprise-Beans mit einer Sicht ohne Schnittstelle erfordern keine Angabe zusätzlicher
Metadaten im Implementierungsdeskriptor oder bei der Verwendung von Annotationen.
Weitere Einzelheiten zu Sichten einer Enterprise-Bean ohne Schnittstelle
finden Sie in der Spezifikation EJB 3.1.
JAX-RS unterstützt die Verwendung von Enterprise-Beans, die eine lokale Geschäftsschnittstelle
deklarieren, und die Verwendung von Enterprise-Beans mit Sichten ohne Schnittstelle.
In dieser Aufgabe ist beschrieben, wie REST-konforme Sichten einer Enterprise-Bean mit einer lokalen Schnittstelle implementiert werden,
um der Enterprise-Bean die Bereitstellung von JAX-RS-Ressourcen zu ermöglichen.
Informationen zu diesem Vorgang
Sie können eine einfache Enterprise-Bean mit JAX-RS-Annotationen erstellen.
Obwohl in dieser Aufgabe genau beschrieben ist, wie REST-konforme Sichten einer Enterprise-Bean
mit lokaler Schnittstelle implementiert werden, müssen Sie unbedingt den vollen Umfang
Ihrer Anwendungsarchitektur berücksichtigen und wissen, wie Sie Ressourcen bereitstellen möchten,
wenn Sie sich für Ihr Ressourcenmodell entscheiden und die für Ihre Enterprise-Bean-Anwendung
geeigneten REST-konformen Sichten bestimmen.
Diese Überlegungen sprengen jedoch den Rahmen dieser Task.
JAX-RS unterstützt Stateless- und Singleton-Session-Beans.
Sie können der lokalen Schnittstelle einer Session-Bean JAX-RS-Annotationen hinzufügen.
Außerdem können Sie mit EJB 3.1 JAX-RS-Annotationen einer EJB-Klasse direkt hinzufügen,
wenn die Enterprise-Bean eine Sicht ohne Schnittstelle bereitstellt.
Mit den Packregeln
der Spezifikation EJB 3.1 können Sie JAX-RS-Enterprise-Beans
der WAR-Datei direkt im Verzeichnis "WEB-INF/classes" oder über eine JAR-Datei im Verzeichnis
"WEB-INF/lib" hinzufügen. Sie können eine Enterprise-Bean mit Annotationen und/oder mit einem
EJB-Implementierungsdeskriptor deklarieren.
JAX-RS-Enterprise-Beans mit Annotationen
in einer eigenständigen Datei oder in einer EJB-JAR-Datei, die in einer EAR-Datei enthalten ist, werden nicht unterstützt.
Bewährtes Verfahren: Obwohl Sie Enterprise-Beans auf verschiedene Arten
deklarieren können, empfiehlt es sich, die lokale EJB-Geschäftsschnittstelle
direkt zu implementieren und die Annotation "@javax.ejb.Local" immer zu deklarieren.
Bei der Verwendung dieser Methode muss die EJB-Bean die lokale Geschäftsschnittstelle
implementieren, die Fehler bei der Eingabe von Methodennamen und Änderungen von Argumenttypen verhindert.
Wenn Sie immer die Annotation "@javax.ejb.Local" verwenden und mehrere Geschäftsschnittstellen vorhanden sind,
können Sie die Geschäftsschnittstelle einfach dem Annotationswert hinzufügen.
Sie können diesen Ansatz auch verwenden, um die Enterprise-Bean mithilfe eines
Implementierungsdeskriptors zu ändern.
bprac
Vorgehensweise
- Erstellen Sie lokale EJB-Schnittstellen für Ihre Enterprise-Bean-Anwendung. Das folgende Beispiel veranschaulicht eine einfache lokale Geschäftsschnittstelle, die lokale EJB-Schnittstelle
"Purchasable", über die Artikel eingekauft werden:
package com.example.jaxrs;
@javax.ws.rs.Path("itemsForPurchase/{itemID}")
public interface Purchasable {
public int getItemsLeft(String itemID);
@javax.ws.rs.POST
public Order purchase(
@javax.ws.rs.PathParam("itemID") String itemID,
@javax.ws.rs.QueryParam("orderId") String orderID);
}
Die Methode "getItemsLeft" ist eine reguläre EJB-Methode, die sich nicht
auf JAX-RS bezieht. Eine Annotation "javax.ws.rs.Path" bestimmt den zu verwendenden HTTP-Anforderungspfad.
Wenn eine HTTP-POST-Anforderung an das Objekt itemsForPurchase/{itemID} abgesetzt wird,
sucht die JAX-RS-Laufzeitumgebung eine EJB-Bean, die die lokale Schnittstelle
Purchasable implementiert, und ruft die Methode "purchase" in der Enterprise-Bean auf.
Sie können die Methode "purchase" trotzdem außerhalb einer Anforderung in der JAX-RS-Laufzeitumgebung verwenden.
Sie können Injektion oder eine JNDI-Suche für eine purchasable-EJB verwenden und die Methode "purchase"
mit den beiden Zeichenfolgeargumenten itemID und orderID aufrufen.
Bewährtes Verfahren: Wenn es mehrere Enterprise-Beans gibt, die eine lokale Geschäftsschnittstelle
implementieren, wählt die JAX-RS-Laufzeitumgebung eine beliebige EJB-Bean aus, die verwendet wird,
wenn eine JAX-RS-Anforderung abgesetzt wird. Es empfiehlt sich, nur eine einzige Bean-Klasse
zu aktivieren, die eine lokale EJB-Schnittstelle mit mit JAX-RS-Annotationen implementiert.
Erstellen Sie, sofern erforderlich, eine separate lokale EJB-Schnittstelle,
verwenden Sie die JAX-RS-Annotationen in der neuen Schnittstelle und ändern Sie dann
die Metadaten für die Bean-Klasse so, dass sie die neue lokale EJB-Schnittstelle implementiert.
bprac
- Erstellen Sie die Enterprise-Bean, die die lokale Geschäftsschnittstelle
implementiert. Das folgende Beispiel veranschaulicht die EJB-Bean "Purchasable":
public int getItemsLeft(String itemID) {
// Anzahl der verbliebenen Artikel zurückgeben
}
public Order purchase(String itemID, String orderId) {
// Angegebenen Artikel der Bestell-ID hinzufügen und zurückgeben
}
}
- Deklarieren Sie die Klasse "Book" als Enterprise-Bean, die eine lokale Schnittstelle
implementiert. Verwenden Sie eine der folgenden Methoden, um Ihre Klasse als Enterprise-Bean zu dekarieren, die
die lokale Schnittstelle implementiert.
Im folgenden Beispiel wird die Klasse "Book" als Enterprise-Bean deklariert, die eine lokale Schnittstelle implementiert:
- Verwenden Sie die EJB-Annotation "@javax.ejb.Stateless" oder "@javax.ejb.Singleton" in der
Klasse "Book", um anzugeben, ob die EJB eine Stateless- oder eine Singleton-EJB sein soll.
Fügen Sie auch eine Annotation "@javax.ejb.Local" mit den lokalen Schnittstellen als Annotationswert hinzu, z. B.:
@javax.ejb.Stateless
@javax.ejb.Local(Purchasable.class)
public class Book {
Wenn Sie mehrere lokale Schnittstellen implementiert haben, fügen Sie die Schnittstellenklassen
dem @javax.ejb.Local-Annotationswert hinzu, z. B.:
@javax.ejb.Local({Purchasable.class, Rentable.class})
- Sie können einen Implementierungsdeskriptor verwenden, um die EJB und die von der EJB implementierten
Geschäftsschnittstellen zu deklarieren, z. B.:
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" version="3.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd">
<!--
Diese Datei muss im Verzeichnis WEB-INF/
der WAR-Datei enthalten sein. Weitere Einzelheiten finden Sie in der Spezifikation EJB 3.1 (20.4).
-->
<enterprise-beans>
<session>
<ejb-name>Book</ejb-name>
<business-local>com.example.jaxrs.Purchasable</business-local>
<ejb-class>com.example.jaxrs.Book</ejb-class>
<session-type>Stateless</session-type>
</session>
</enterprise-beans>
</ejb-jar>
Wenn Sie mehrere lokale Geschäftsschnittstellen implementiert haben, müssen Sie
jeder lokalen Schnittstelle in Ihrer Bean-Definition Elemente vom Typ "business-local" hinzufügen.
- Wenn Sie nur eine einzige lokale Geschäftsschnittstelle haben, können Sie die Schnittstelle direkt implementieren, z. B.:
@javax.ejb.Stateless
public class Book implements Purchasable {
- (Optional) Fügen Sie Ihren JAX-RS-EJB-Klassen mit @javax.annotation.Resource annotierte
Java-EE-Ressourcenfelder und -Eigenschaften
hinzu, um ohne großen Aufwand auf Ressourcen in Ihrer Anwendung zuzugreifen. Die Java-EE-Injektionen
funktionieren nicht in einfachen Java-Klassen mit JAX-RS-Annotationen.
Die Injektion von mit @javax.annotation.Resource annotierten Java-EE-Ressourcenfeldern
und -Eigenschaften in Ihre JAX-RS-EJB-Klassen funktioniert nur, wenn Ihre mit JAX-RS annotierten Klassen eine
Enterprise-Bean oder eine JCDI-verwaltete (Java Context
and Dependency Injection, JSR-299) Bean sind, z. B.:
package com.example.jaxrs;
@javax.ejb.Stateless
@javax.ejb.Local(Purchasable.class)
public class Book implements Purchasable {
@javax.annotation.Resource(name="jdcb/TestDataSource")
private javax.sql.DataSource datasource;
public int getItemsLeft(String itemID) {
// Liest aus der Datenquelle.
// Gibt die Anzahl der verbliebenen Artikel zurück.
}
public Order purchase(String itemID, String orderId) {
// Liest aus der Datenquelle.
// Fügt den angegebenen Artikel der Bestell-ID hinzu und gibt ihn zurück.
}
}
Wenn eine Datenquelle ordnungsgemäß und mit dem richtigen JNDI-Namen konfiguriert ist, wird in diesem Beispiel
ein DataSource-Objekt in die Ressourcenklasse eingefügt.
- (Optional) Verwenden Sie die JAX-RS-Injektion @javax.ws.rs.core.Context, damit Sie auf Informationen zur Anforderung
zugreifen können. Sie können Ihrer JAX-RS-EJB-Klasse ein
@javax.ws.rs.core.Context-Feld "UriInfo" hinzufügen, um auf Informationen zum Anforderungs-URI zuzugreifen, z. B.:
package com.example.jaxrs;
@javax.ejb.Stateless
@javax.ejb.Local(Purchasable.class)
public class Book implements Purchasable {
@javax.ws.rs.core.Context
private UriInfo uriInfo;
public int getItemsLeft(String itemID) {
// Anzahl der verbliebenen Artikel zurückgeben
}
public Order purchase(String itemID, String orderId) {
// Angegebenen Artikel der Bestell-ID hinzufügen und zurückgeben
}
}
Wenn Sie Parameter der Anforderung lesen möchten, z. B. @javax.ws.rs.HeaderParam,
@javax.ws.rs.QueryParam und @javax.ws.rs.PathParam, fügen Sie einen Parameter zu Ihrer Ressourcenmethode
hinzu. Beispiel:
package com.example.jaxrs;
@javax.ws.rs.Path("itemsForPurchase/{itemID}")
public interface Purchasable {
public int getItemsLeft(String itemID);
@javax.ws.rs.POST
public Order purchase(
@javax.ws.rs.PathParam("itemID") String itemID,
@javax.ws.rs.QueryParam("orderId") String orderID);
}
package com.example.jaxrs;
@javax.ejb.Stateless
@javax.ejb.Local(Purchasable.class)
public class Book implements Purchasable {
@javax.ws.rs.core.Context
private UriInfo uriInfo;
public int getItemsLeft(String itemID) {
// Gibt die Anzahl der verbliebenen Artikel zurück.
}
public Order purchase(String itemID, String orderId) {
// Die Methodenparameter enthalten die Anforderungswerte.
// Angegebenen Artikel der Bestell-ID hinzufügen und zurückgeben
}
/* Das folgende Feld wird nicht gesetzt. */
@javax.ws.rs.QueryParam("q")
private String willNotWork;
@javax.ws.rs.QueryParam("q")
public void setMyQueryParam(String q) {
/* Diese Eigenschaft wird nicht gesetzt. */
}
}
Unterstützte Konfigurationen: Sie müssen die JAX-RS-Parameterannotationen den Ressourcenmethoden
in der EJB-Geschäftsschnittstelle hinzufügen, wenn Geschäftsschnittstellen verwendet werden.
Sie können nicht der Implementierungsbean hinzugefügt werden.
sptcfg
- Packen Sie die Enterprise-Beans in das Verzeichnis "WEB-INF/classes"
der WAR-Datei oder in eine JAR-Datei, die im Verzeichnis "WEB-INF/lib"
der WAR-Datei enthalten ist.
Wenn ein Client eine Anforderung an eine Enterprise-Bean mit JAX-RS-Annotationen absetzt,
sucht die JAX-RS-Laufzeitumgebung eine EJB-Instanz der Klasse und verwendet diese, um anschließend die
JAX-RS-Ressourcenmethode aufzurufen.
Ergebnisse
Sie haben eine vorhandene Enterprise-Bean mit lokalen Schnittstellen
aktiviert, damit JAX-RS-Ressourcen zur Verwendung bereitgestellt werden.