Comrades, I write a web service on Java, the client part in C #, I also use the hibernate framework. Model class example:
@Entity @Table(name = "garages") public class Garage implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private int id; @Column(name = "description") private String decription; @ManyToOne(cascade = CascadeType.REFRESH) @JoinColumn(name = "owner_id") private Owner owner; @OneToMany(cascade = CascadeType.ALL, mappedBy = "garage") private List<Car> cars; public Garage() { } public Garage(int id, String decription, Owner owner, List<Car> cars) { this.decription = decription; this.owner = owner; this.cars = cars; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getDecription() { return decription; } public void setDecription(String decription) { this.decription = decription; } public Owner getOwner() { return owner; } public void setOwner(Owner owner) { this.owner = owner; } public List<Car> getCars() { return cars; } public void setCars(List<Car> cars) { this.cars = cars; } } @Entity @Table(name = "owners") public class Owner implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private int id; @Column(name = "name") private String name; @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner") private List<Car> ownerCars; @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner") private List<Garage> ownerGarages; public Owner() { } public Owner(int id, List<Car> ownerCars, List<Garage> ownerGarages) { this.id = id; this.ownerCars = ownerCars; this.ownerGarages = ownerGarages; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public List<Car> getOwnerCars() { return ownerCars; } public void setOwnerCars(List<Car> ownerCars) { this.ownerCars = ownerCars; } public List<Garage> getOwnerGarages() { return ownerGarages; } public void setOwnerGarages(List<Garage> ownerGarages) { this.ownerGarages = ownerGarages; } } DAO implementation:
public class OwnerDaoImpl implements OwnerDao { private Session session = null; @Override public void addOwner(Owner owner) { openSessionAndBeginTransaction(); session.save(owner); closeSessionAndCommit(); } @Override public ArrayList<Owner> getAllOwners() { openSessionAndBeginTransaction(); List<Owner> owners = session.createQuery("from Owner").list(); closeSessionAndCommit(); return (ArrayList)owners; } @Override public Owner getOwnerForGarageId(int idGarage) { openSessionAndBeginTransaction(); Query query = session.createQuery("from Garage where id = :param"); query.setParameter("param", idGarage); Garage garage = (Garage) query.uniqueResult(); closeSessionAndCommit(); return garage.getOwner(); } @Override public Owner getOwnerForCarId(int idCar) { openSessionAndBeginTransaction(); Query query = session.createQuery("from Car where id = :param"); query.setParameter("param", idCar); Car car = (Car) query.uniqueResult(); closeSessionAndCommit(); return car.getOwner(); } private void openSessionAndBeginTransaction() { session = HibernateUtil.getSessionFactory().openSession(); session.beginTransaction(); } private void closeSessionAndCommit() { session.getTransaction().commit(); session.close(); } @Override public ArrayList<Garage> getListGaragesForOwnerId(int ownerId) { openSessionAndBeginTransaction(); Query query = session.createQuery("from Car where owner_id = :param"); query.setParameter("param", ownerId); List<Garage> result = query.list(); closeSessionAndCommit(); return (ArrayList) result; } @Override public Owner getOwnerForName(String name) { openSessionAndBeginTransaction(); Query query = session.createQuery("from Owner where name = :param"); query.setParameter("param", name); Owner result = (Owner) query.uniqueResult(); return result; } } And the service itself:
@WebService(serviceName = "GaragesServices") public class GarageServices implements CarServiceInterface, GarageServiceInterface, OwnerServiceInterface { CarDao carDao = new CarDaoImpl(); GarageDao garageDao = new GarageDaoImpl(); OwnerDao ownerDao = new OwnerDaoImpl(); Sender postSender = new Sender(); /** * * @param garage */ @Override @WebMethod public void addGarage(@WebParam(name = "garage") Garage garage) { garageDao.addGarage(garage); } /** * * @return */ @Override @WebMethod public ArrayList<Garage> getAllGarages() { return garageDao.getAllGarages(); } /** * * @param ownerId * @return */ @Override @WebMethod public ArrayList<Garage> getListGaragesForOwnerId(@WebParam(name = "ownerId") int ownerId) { return garageDao.getListGaragesForOwnerId(ownerId); } /** * * @param idCar * @return */ @Override @WebMethod public Garage getGarageForCarId(@WebParam(name = "idCar") int idCar) { return garageDao.getGarageForCarId(idCar); } /** * * @param owner */ @Override @WebMethod public void addOwner(@WebParam(name = "owner") Owner owner) { ownerDao.addOwner(owner); } /** * * @return */ @Override @WebMethod public ArrayList<Owner> getAllOwners() { return ownerDao.getAllOwners(); } /** * * @param idGarage * @return */ @Override @WebMethod public Owner getOwnerForGarageId(@WebParam(name = "idGarage") int idGarage) { return ownerDao.getOwnerForGarageId(idGarage); } /** * * @param idCar * @return */ @Override @WebMethod public Owner getOwnerForCarId(@WebParam(name = "idCar") int idCar) { return ownerDao.getOwnerForCarId(idCar); } /** * * @param car */ @Override @WebMethod public void addCar(@WebParam(name = "car") Car car) { carDao.addCar(car); } /** * * @return */ @Override @WebMethod public ArrayList<Car> getCars() { return carDao.getCars(); } /** * * @param ownerId * @return */ @Override @WebMethod public ArrayList<Car> getListCarsForOwnerId(@WebParam(name = "ownerId") int ownerId) { return carDao.getListCarsForOwnerId(ownerId); } /** * * @param name * @return */ @Override @WebMethod public ArrayList<Car> getListCarsForOwnerName(@WebParam(name = "name") String name) { return carDao.getListCarsForOwnerName(name); } /** * * @param idGarage * @return */ @Override @WebMethod public ArrayList<Car> getListCarsForGarageId(@WebParam(name = "idGarage") int idGarage) { return carDao.getListCarsForGarageId(idGarage); } /** * Операция веб-службы * @param owner */ @WebMethod(operationName = "sendMailToAdministrator") public void sendMailToAdministrator(@WebParam(name = "owner") Owner owner) { postSender.send(owner); } /** * Операция веб-службы */ @Override @WebMethod(operationName = "getAllGaragesForOwnerName") public ArrayList<Garage> getAllGaragesForOwnerName(@WebParam(name = "name") String name) { return garageDao.getListGaragesForOwnerName(name); } @Override @WebMethod public Owner getOwnerByName(@WebParam(name = "name")String name) { return ownerDao.getOwnerForName(name); } }
Client side code:
public partial class Form1 : Form { private ClientServiceManagement client = new ClientServicesGarageManagement(); private garage[] garagesClient = null; private car[] carsInGarage = null; private String header = "Пользователь не найден!"; private String emptyField = "Пустое поле!"; private String emptyMessage = "Пожалуйста, введите данные для поиска!"; private garage garageChoosen = null; private String error = "Заполните поле марки машины или выберите гараж для добавления"; private owner user = null; private MessageBoxButtons buttons; private DialogResult result; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { comboBox1.Items.Clear(); listView1.Items.Clear(); if (validateSearchBox(textBox1.Text.Length)) { user = client.getOwnerByName(textBox1.Text); if(user == null) { String message = "Владельца гаража с именем " + textBox1.Text + " не найден. Измените параметры поиска"; buttons = MessageBoxButtons.OK; result = MessageBox.Show(message, header, buttons); if(result == System.Windows.Forms.DialogResult.OK) { textBox1.Text = ""; } } try { label5.Text = user.name; initGaragesCount(user); } catch (NullReferenceException e1) { e1.ToString(); } } else { buttons = MessageBoxButtons.OK; result = MessageBox.Show(emptyMessage, emptyField, buttons); } } private void button2_Click(object sender, EventArgs e) { car car = new car(); if (textBox3.Text != "" && garageChoosen != null) { car.markAndModel = textBox3.Text; car.owner = user; car.garage = garageChoosen; client.addCar(car); initializeGarage(garageChoosen.id); } else { buttons = MessageBoxButtons.OK; result = MessageBox.Show(error, emptyField, buttons); } } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { int indexChoose = comboBox1.SelectedIndex; garageChoosen = garagesClient[indexChoose]; initializeGarage(garageChoosen.id); } private bool validateSearchBox(int length) { if (length != 0) { return true; } return false; } private void clearInformation() { comboBox1.Items.Clear(); listView1.Items.Clear(); } private void initGaragesCount(owner user) { garagesClient = client.getListGaragesByOwnerId(user.id); foreach (garage element in garagesClient) { comboBox1.Items.Add(element.id + " " + element.decription); } } private void initializeGarage(int idGarage) { carsInGarage = client.getCarsByGarageId(idGarage); foreach(car oneCar in carsInGarage) { listView1.Items.Add(oneCar.id + " " + oneCar.markAndModel); } } } }
The essence of the problem is that when calling the search owner by name on the side of the service catches an exception
Warning: StandardWrapperValve[GarageServices]: Servlet.service() for servlet GarageServices threw exception com.sun.istack.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: com.ua.model.Owner@795dade6 -> com.ua.model.Garage@2c848766 -> com.ua.model.Owner@795dade6 And on the client - System.ServiceModel.ProtocolException
System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3) в System.Xml.XmlExceptionHelper.ThrowUnexpectedEndOfFile(XmlDictionaryReader reader) в System.Xml.XmlBaseReader.MoveToEndOfFile() в System.Xml.XmlUTF8TextReader.Read() в System.ServiceModel.Channels.Message.ReadStartBody(XmlDictionaryReader reader, EnvelopeVersion envelopeVersion, Boolean& isFault, Boolean& isEmpty) в System.ServiceModel.Channels.ReceivedMessage.ReadStartBody(XmlDictionaryReader reader) в System.ServiceModel.Channels.BufferedMessage..ctor(IBufferedMessageData messageData, RecycledMessageState recycledMessageState, Boolean[] understoodHeaders, Boolean understoodHeadersModified) в System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.ReadMessage(ArraySegment`1 buffer, BufferManager bufferManager, String contentType) в System.ServiceModel.Channels.MessageEncoder.ReadMessage(Stream stream, BufferManager bufferManager, Int32 maxBufferSize, String contentType) в System.ServiceModel.Channels.HttpInput.ReadChunkedBufferedMessage(Stream inputStream) BUT!!! If the entity Owner that I request is not connected with anyone, then there is no exception. As I read the problem is that the collections are heavy. Found solutions, but they did not fit. Maybe something is not right. Help in solving the problem