I've managed to create my first Web Services interface that retrieves a record
from a MySQL db via an EJB3.0 bean generated by Hibernate using reverse
engineering. However, I can't return this object to the remote client because
I get the following error:
15:22:47,324 INFO [STDOUT] Subscriber.find(): em is not null; returning
subscriber for guid = CRUNCH-DEFAULT-SUPERUSER
| 15:22:47,339 INFO [STDOUT] Count : 7
| 15:22:47,339 INFO [STDOUT] Subscriber name : SuperUser
| 15:22:47,340 INFO [STDOUT] Subscriber email: [EMAIL PROTECTED]
| 15:22:47,406 ERROR [RequestHandlerImpl] Error processing web service request
| org.jboss.ws.WSException: javax.xml.ws.WebServiceException:
javax.xml.bind.MarshalException
| - with linked exception:
| [com.sun.istack.SAXException2: A cycle is detected in the object graph.
This will cause infinitely deep XML: [EMAIL PROTECTED] -> [EMAIL PROTECTED] ->
[EMAIL PROTECTED]
It seems that if your returned object includes a OneToMany mapping you get this
problem. I can reference the object on the server side and return individual
fields from it to the remote client, but I can't return the whole object.
Since the class is being automatically generated with Hibernate, I'm wondering
how I can return any db objects to callers? In fact, what if I wanted to
create a new class, one that doesn't represent a table in the db, and return
that? How does the client reference this class? Note that I'm using wsconsume
to generate the client side classes used to interact with the Web Service. I
know this latter is a WS question and not an EJB question, but my initial
problem still stands - what can I do to return this EJB that has OneToMany
mappings in it without getting the infinite XML error?
This is what my Web Services/Session Bean looks like:
package com.cei.crunch.server.ws.SubscriberServices;
|
| import javax.ejb.*;
| import javax.jws.WebService;
| import javax.jws.WebMethod;
| import javax.jws.soap.SOAPBinding;
| import javax.persistence.*;
| import javax.naming.InitialContext;
| import javax.transaction.UserTransaction;
| import javax.annotation.Resource;
|
| import com.cei.crunch.ejb.Subscriber;
| import com.cei.crunch.ejb.SubscriberHome;
|
| /* Make this an EJB3 service endpoint. */
| @Stateless
| @Remote(SubscriberServices.class)
|
| /* Make this an Web Services endpoint. */
| @WebService(
| name = "SubscriberWS",
| endpointInterface =
"com.cei.crunch.server.ws.SubscriberServices.SubscriberServicesEndpoint"
| )
| @SOAPBinding(style = SOAPBinding.Style.RPC)
|
| /**
| * The .Crunch interface to Subscriber Services
| */
| public class SubscriberServices implements SubscriberServicesEndpoint {
|
| private UserTransaction utx;
| private EntityManager em;
|
| @WebMethod
| public String findSubscriber(String guid)
| {
| Subscriber s = null;
|
| InitialContext ctx = null;
| EntityManager em = null;
| try {
| ctx = new InitialContext();
| em = (EntityManager) ctx.lookup("java:/CrunchPersistence");
| utx = (UserTransaction)
ctx.lookup("java:/comp/UserTransaction");
| }
| catch (Exception e)
| {
| // throw new WebServiceException(ex);
| System.out.println("Subscriber.find(): context lookup
failure.");
| e.printStackTrace();
| return null;
| }
|
| if ( em == null )
| {
| System.out.println("Subscriber.find(): em is null; can't find
subscriber");
| }
| else
| {
| System.out.println("Subscriber.find(): em is not null;
returning subscriber for guid = " + guid);
| try {
| utx.begin();
| s = em.find(Subscriber.class, guid);
| int count = s.getCrunchroleses().size();
| if ( s != null )
| {
| System.out.println("Count : " + count);
| System.out.println("Subscriber name : " +
s.getFirstname());
| System.out.println("Subscriber email: " +
s.getEmailAddress());
| }
| utx.commit();
| }
| catch (Exception e)
| {
| System.out.println("Subscriber.find(): find problem.");
| e.printStackTrace();
| }
| }
| if ( s != null )
| return s.getGuid();
| else
| return null;
| }
|
| }
Some notes on this. First, injection is not working under Web Services in
4.2.2GA (see my previous posts in the WS forum -
http://www.jboss.com/index.html?module=bb&op=viewtopic&t=126927) so the context
and transaction have to be created manually. Second, if you don't reference
the size of one of the Set's in this EJB before referencing the fields you get
LazyInitializationException errors.
The Subscriber table looks like this - note that there are no foreign key
references here, but other tables have foreign key references back to this
table which causes the EJB for this table (as generated by Hibernate) to
include the foreign key methods.
create table Subscriber (
| guid varchar(50) not null,
| Username varchar(256), -- The login id for this
subscriber
| password varchar(256), -- The password for this
subscriber; will need encryption set for this
|
| addr1 varchar(256), -- Home address
| addr2 varchar(256), -- Home address
| city varchar(256), -- City or Town of origin
| province varchar(256), -- State or Province
|
| country varchar(256), --
| postalCode varchar(50), --
| emailAddress varchar(1024), --
| phone varchar(50), --
| latitude float, -- Used only to place
subscribers on a map
| longitude float, -- Used only to place
subscribers on a map
|
| firstname varchar(256), -- The subscriber first name
| lastname varchar(256), -- The subscriber last name
| organizationGuid varchar(50), -- The organization this
subscriber belongs to, if any
| groupGuid varchar(50), -- The group within the
organization, if any
| teamGuid varchar(50), -- The team the subscriber
chose, if any
| viewLevelGuid varchar(50), -- The view level this
subscriber has
| viewAccessGuid varchar(50), -- The view level this
subscriber can see
| lastLogin varchar(50), -- When the subscriber last
logged in
| state int, -- 0: new, 1: active, 2:
inactive, 3: deleted, 4: banned
| priority int, -- Higher values have higher
priority
|
| PRIMARY KEY(guid)
| )
The EJB generated by hbm2java looks like this:
package com.cei.crunch.ejb;
| // Generated Jan 7, 2008 3:51:39 PM by Hibernate Tools 3.2.0.CR1
|
|
| import java.util.HashSet;^M
| import java.util.Set;^M
| import javax.persistence.Column;^M
| import javax.persistence.Entity;^M
| import javax.persistence.FetchType;^M
| import javax.persistence.Id;^M
| import javax.persistence.OneToMany;^M
| import javax.persistence.Table;^M
|
| /**
| * Subscriber generated by hbm2java
| */
| @Entity
| @Table(name="subscriber"
| ,catalog="crunch"
| )
| public class Subscriber implements java.io.Serializable {
|
|
| private String guid;
| private String username;
| private String password;
| private String addr1;
| private String addr2;
| private String city;
| private String province;
| private String country;
| private String postalCode;
| private String emailAddress;
| private String phone;
| private Float latitude;
| private Float longitude;
| private String firstname;
| private String lastname;
| private String organizationGuid;
| private String groupGuid;
| private String teamGuid;
| private String viewLevelGuid;
| private String viewAccessGuid;
| private String lastLogin;
| private Integer state;
| private Integer priority;
| private Set<Subscribersession> subscribersessions = new
HashSet<Subscribersession>(0);
| private Set<Crunchroles> crunchroleses = new HashSet<Crunchroles>(0);
|
|
| public Subscriber() {
| }
|
|
| public Subscriber(String guid) {
| this.guid = guid;
| }
| public Subscriber(String guid, String username, String password, String
addr1, String addr2, String city, String province, String country, String
postalCode, String emailAddress, String phone, Float latitude, Float longitude,
String firstname, String lastname, String organizationGuid, String groupGuid,
String teamGuid, String viewLevelGuid, String viewAccessGuid, String lastLogin,
Integer state, Integer priority, Set<Subscribersession> subscribersessions,
Set<Crunchroles> crunchroleses) {
| this.guid = guid;
| this.username = username;
| this.password = password;
| this.addr1 = addr1;
| this.addr2 = addr2;
| this.city = city;
| this.province = province;
| this.country = country;
| this.postalCode = postalCode;
| this.emailAddress = emailAddress;
| this.phone = phone;
| this.latitude = latitude;
| this.longitude = longitude;
| this.firstname = firstname;
| this.lastname = lastname;
| this.organizationGuid = organizationGuid;
| this.groupGuid = groupGuid;
| this.teamGuid = teamGuid;
| this.viewLevelGuid = viewLevelGuid;
| this.viewAccessGuid = viewAccessGuid;
| this.lastLogin = lastLogin;
| this.state = state;
| this.priority = priority;
| this.subscribersessions = subscribersessions;
| this.crunchroleses = crunchroleses;
| }
|
| @Id
|
| @Column(name="guid", nullable=false, length=50)
| public String getGuid() {
| return this.guid;
| }
|
|
| public void setGuid(String guid) {
| this.guid = guid;
| }
|
| @Column(name="Username", length=256)
| public String getUsername() {
| return this.username;
| }
|
| public void setUsername(String username) {
| this.username = username;
| }
|
| @Column(name="password", length=256)
| public String getPassword() {
| return this.password;
| }
|
| public void setPassword(String password) {
| this.password = password;
| }
|
| @Column(name="addr1", length=256)
| public String getAddr1() {
| return this.addr1;
| }
|
| public void setAddr1(String addr1) {
| this.addr1 = addr1;
| }
|
| @Column(name="addr2", length=256)
| public String getAddr2() {
| return this.addr2;
| }
|
| public void setAddr2(String addr2) {
| this.addr2 = addr2;
| }
|
| @Column(name="city", length=256)
| public String getCity() {
| return this.city;
| }
|
| public void setCity(String city) {
| this.city = city;
| }
|
| @Column(name="province", length=256)
| public String getProvince() {
| return this.province;
| }
|
| public void setProvince(String province) {
| this.province = province;
| }
|
| @Column(name="country", length=256)
| public String getCountry() {
| return this.country;
| }
|
| public void setCountry(String country) {
| this.country = country;
| }
|
| @Column(name="postalCode", length=50)
| public String getPostalCode() {
| return this.postalCode;
| }
|
| public void setPostalCode(String postalCode) {
| this.postalCode = postalCode;
| }
|
| @Column(name="emailAddress", length=1024)
| public String getEmailAddress() {
| return this.emailAddress;
| }
|
| public void setEmailAddress(String emailAddress) {
| this.emailAddress = emailAddress;
| }
|
| @Column(name="phone", length=50)
| public String getPhone() {
| return this.phone;
| }
|
| public void setPhone(String phone) {
| this.phone = phone;
| }
|
| @Column(name="latitude", precision=12, scale=0)
| public Float getLatitude() {
| return this.latitude;
| }
|
| public void setLatitude(Float latitude) {
| this.latitude = latitude;
| }
|
| @Column(name="longitude", precision=12, scale=0)
| public Float getLongitude() {
| return this.longitude;
| }
|
| public void setLongitude(Float longitude) {
| this.longitude = longitude;
| }
|
| @Column(name="firstname", length=256)
| public String getFirstname() {
| return this.firstname;
| }
|
| public void setFirstname(String firstname) {
| this.firstname = firstname;
| }
|
| @Column(name="lastname", length=256)
| public String getLastname() {
| return this.lastname;
| }
|
| public void setLastname(String lastname) {
| this.lastname = lastname;
| }
|
| @Column(name="organizationGuid", length=50)
| public String getOrganizationGuid() {
| return this.organizationGuid;
| }
|
| public void setOrganizationGuid(String organizationGuid) {
| this.organizationGuid = organizationGuid;
| }
|
| @Column(name="groupGuid", length=50)
| public String getGroupGuid() {
| return this.groupGuid;
| }
|
| public void setGroupGuid(String groupGuid) {
| this.groupGuid = groupGuid;
| }
|
| @Column(name="teamGuid", length=50)
| public String getTeamGuid() {
| return this.teamGuid;
| }
|
| public void setTeamGuid(String teamGuid) {
| this.teamGuid = teamGuid;
| }
|
| @Column(name="viewLevelGuid", length=50)
| public String getViewLevelGuid() {
| return this.viewLevelGuid;
| }
|
| public void setViewLevelGuid(String viewLevelGuid) {
| this.viewLevelGuid = viewLevelGuid;
| }
|
| @Column(name="viewAccessGuid", length=50)
| public String getViewAccessGuid() {
| return this.viewAccessGuid;
| }
|
| public void setViewAccessGuid(String viewAccessGuid) {
| this.viewAccessGuid = viewAccessGuid;
| }
|
| @Column(name="lastLogin", length=50)
| public String getLastLogin() {
| return this.lastLogin;
| }
|
| public void setLastLogin(String lastLogin) {
| this.lastLogin = lastLogin;
| }
|
| @Column(name="state")
| public Integer getState() {
| return this.state;
| }
|
| public void setState(Integer state) {
| this.state = state;
| }
|
| @Column(name="priority")
| public Integer getPriority() {
| return this.priority;
| }
|
| public void setPriority(Integer priority) {
| this.priority = priority;
| }
| @OneToMany(fetch=FetchType.LAZY, mappedBy="subscriber")
| public Set<Subscribersession> getSubscribersessions() {
| return this.subscribersessions;
| }
|
| public void setSubscribersessions(Set<Subscribersession>
subscribersessions) {
| this.subscribersessions = subscribersessions;
| }
| @OneToMany(fetch=FetchType.LAZY, mappedBy="subscriber")
| public Set<Crunchroles> getCrunchroleses() {
| return this.crunchroleses;
| }
|
| public void setCrunchroleses(Set<Crunchroles> crunchroleses) {
| this.crunchroleses = crunchroleses;
| }
| }
|
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4117758#4117758
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4117758
_______________________________________________
jboss-user mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/jboss-user