# Jaxb und JPA: A cycle is detected in the object graph



## mdolphin (27. Okt 2011)

Ich möchte testweise mal per Jaxb eine Rechnung mit ihren Rechnungspositionen ausgeben. Die beiden entsprechenden Java Klassen haben die folgenden Annotationen:

Die Klasse für die Rechnung:

```
@XmlRootElement
@Entity
@Table(name="Invoice")
public class Invoice {
	@Id
	@GeneratedValue(strategy = GenerationType.TABLE)
	private int id;
...
        @OneToMany(mappedBy="invoice", cascade = {CascadeType.ALL })
	@PrivateOwned
	private List<InvoiceDetail> details = new ArrayList<InvoiceDetail>(); 
....
```

..und für die Rechnungspositionen:


```
@Entity
@Table(name="InvoiceDetail")
public class InvoiceDetail {
	
	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE)
	private int id;
...
        @ManyToOne
	@JoinColumn(name="INVOICE_ID", nullable=false)
        private Invoice invoice;

        
        public Invoice getInvoice() {
		return invoice;
	}

	public void setInvoice(Invoice invoice) {
		this.invoice = invoice;
	}
....
```


In der Datenbank sieht das dann so aus, dass ich in der Tabelle mit den Rechnungsdetails schön den Fremdschlüssel für die Rechnung drin stehen habe.

Beim Versuch das Ganze par Jaxb als XML oder JSON auszugeben bekomme ich regelmäßig eine Exception:


```
A cycle is detected in the object graph. This will cause infinitely deep XML: de.meintest.model.Invoice@4735572b -> de.meintest.model.InvoiceDetail@3717ee94 -> de.meintest.model.Invoice@4735572b
```

Was ich schon probiert habe, sind folgende Variationen:
In der Klasse InvoiceDetail..


```
@ManyToOne(fetch=FetchType.LAZY)
	@XmlInverseReference(mappedBy="details")
	@XmlTransient
	private Invoice invoice;
...
```

....natürlich auch einzeln und in beliebigen Kombinationen. Dann gibt es wohl noch @XmlIDREF und @XmlID, die mich aber auch nicht weiter bringen, weil ich ja keinen String Wert mappe.

Kann mir bitte jemand sagen, wie man eine 1:n Beziehung mit JPA anlegt, die dann bei der Verwendung von jaxb nicht zu diesem Fehler führt?

Danke im Voraus

Michael


----------



## maki (27. Okt 2011)

Wenn man nach der Fehlermeldung in diesem Kontext sucht (Google),

findet man Vorschläge das man MOXy als JAXB Implemntierung nehmen sollte, da dort die @XmlInverseReference Annotation unterstützt wird.
Dein Problem ist nciht eine 1:n Beziehung, sondern die Bidirektionale Beziehung zwischen Invoice & InvoiceDetail.


----------



## mdolphin (27. Okt 2011)

Naja, ich bin einigermaßen auf eclipselink festgelegt, daher habe ich MOXy noch nicht probiert. Ich dachte mir, dass wohl auch andere Leute evtl. eclipselink mit JAXB einsetzen. 

Eigentlich brauche ich diese Biderktionale Beziehung gar nicht, aber bei @OneToMany scheint es nicht ohne zu gehen. Alle meine 1:1 Beziehungen, die noch an der Rechnung hängen funktionieren bestens, nur die 1:n Beziehung macht Probleme. Sobald ich die Annotation @ManyToOne bei den Rechnungsdetails weglasse, gibt es Foreign Key Probleme beim Speichern neuer Rechnungen. 

Wenn Du weißt wie ich eine unidirektionae 1:n Beziehung mit Eclipselink erstellen kann, ist das ja auch schon eine Lösung für mein Problem.


----------



## maki (27. Okt 2011)

> Wenn Du weißt wie ich eine unidirektionae 1:n Beziehung mit Eclipselink erstellen kann, ist das ja auch schon eine Lösung für mein Problem.


Komische Frage imho, du hast eine viel komplexere Lösung als du willst .. 

Das ist einfach: Lass das Invoice Attribut bei InvoiceDetail weg.

Nebenbei bemerkt, MOXy ist EclipseLink...

Bist du sicher dass du die Doku zu JPA, EclipseLink und JAXB/EclipseLink gelesen hast?


----------



## mdolphin (27. Okt 2011)

Soso: MOXy ist Eclipselink 

Tja wenn es mal so einfach wäre. Ich muss sagen, bei all den verschiedenen Varianten, die ich jetzt schon ausprobiert habe, habe ich schon etwas den Überblick verloren.

Aber wenn ich, wie Du vorschlägst, das Invoice Attribut in den InvoiceDetails weglasse, meckert eclipse sofort in der Klasse Invoice. Dort steht dann als Fehler neben dem "mappedBy=invoice" 

_In attribute 'details', the "mapped by" value 'invoice' cannot be resolved to an attribute on the target entity._

Also habe ich es wieder eingefügt, mit und ohne @ManyToOne, mit Anotationen am Getter und Setter usw, usw. Alles was man so beim Googeln in irgendwelchen Beispielen findet. (wie z.B. hier:EclipseLink/UserGuide/JPA/Basic JPA Development/Mapping/Relationship Mappings/Collection Mappings/OneToMany - Eclipsepedia


Auch in der Eclipselink (aka. MOXy) Doku wird das mit den Biderektionalen Links gemacht:

EclipseLink/Examples/MOXy/JPA/Relationships - Eclipsepedia siehe One To Many Abschnitt. Und: Ja, das mit @XmlInverseReference hatte ich auch schon versucht.


Naja, weiterfummeln...;(


----------



## maki (28. Okt 2011)

Wenn du das Invoice Attribut in InvoiceDetail weglässt, musst du natürlich auch das "mappedBy " weglassen in Invoice bei den InvoiceDetails.

Wenn du nur wild rumprobierst solltest du wenigstens deine Experimente zeigen, sonst kann man nur mutmassen.


----------

