2014-06-07 14 views
5

Mam pewne problemy w serwecie, w której za każdym razem zmieniam opcję w rozwijanym menu, inna wartość zostanie przekazana do serwletu, a następnie w nieskończoną pętlę. Gdy nie zmieniam opcji (brak zmiany wartości) w menu rozwijanym, nie występuje błąd.Servlet Gson(). ToJson infinite loop

Oto mycode:

My Javascript:

<script> 

function loadStaff(){ 
//dropdown 
var positionDropDown = document.getElementById("positionsDropdown"); 
//value of the drop down 
var positionID = positionDropDown.options[positionDropDown.selectedIndex].value; 

    $.getJSON('loadStaff?positionID=' + positionID, function(data) { 
      -- no populate code yet 
}); 
} 
</script> 

Moja AjaxServlet:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 

     String userPath = request.getServletPath(); 

    if (userPath.equals("/loadStaff")) { 

     String positionID = request.getParameter("positionID"); 
     Position position = positionFacade.find(Integer.parseInt(positionID)); 
     Collection staffCollection = position.getStaffCollection(); 
     List<Staff> staffList = new ArrayList(staffCollection); 

     String staffListJson = new Gson().toJson(staffList); 
     response.setContentType("application/json"); 
     response.setCharacterEncoding("UTF-8"); 
     response.getWriter().write(staffListJson); 

    } 

} 

Po debuggig. Błąd pojawia się w wierszu:

String staffListJson = new Gson().toJson(staffList); 

błąd wyjściowa:

> INFO: WebModule[null] ServletContext.log(): The server side 
> component of the HTTP Monitor has detected a 
> java.lang.StackOverflowError. This happens when there is an infinite 
> loop in the web module. Correct the cause of the infinite loop before 
> running the web module again. 
> 
> INFO: The server side component of the HTTP Monitor has detected a 
> java.lang.StackOverflowError. This happens when there is an infinite 
> loop in the web module. Correct the cause of the infinite loop before 
> running the web module again. WARNING: 
> StandardWrapperValve[AjaxServlet]: Servlet.service() for servlet 
> AjaxServlet threw exception java.lang.StackOverflowError 

> WARNING: StandardWrapperValve[AjaxServlet]: Servlet.service() for 
> servlet AjaxServlet threw exception java.lang.StackOverflowError at 
> sun.util.calendar.ZoneInfo.getOffsets(ZoneInfo.java:248) at 
> java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2276) 
> at 
> java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2248) 
> at java.util.Calendar.setTimeInMillis(Calendar.java:1140) at 
> java.util.Calendar.setTime(Calendar.java:1106) at 
> java.text.SimpleDateFormat.format(SimpleDateFormat.java:955) at 
> java.text.SimpleDateFormat.format(SimpleDateFormat.java:948) at 
> java.text.DateFormat.format(DateFormat.java:336) at 
> com.google.gson.internal.bind.DateTypeAdapter.write(DateTypeAdapter.java:90) 
> at 
> com.google.gson.internal.bind.DateTypeAdapter.write(DateTypeAdapter.java:41) 
> at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
> at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:892) at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
> at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
> at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:892) at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
> at 
> com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89) 
> at 
> com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195) 
> at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:892) 

Zauważyłem również, że te ślady są po prostu powtarzając wyjście stacktrace;

EDIT: klasa Pracownicy

@Entity 
public class Staff implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "id") 
    private Integer id; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 45) 
    @Column(name = "last_name") 
    private String lastName; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 45) 
    @Column(name = "first_name") 
    private String firstName; 
    @Size(max = 45) 
    @Column(name = "middle_name") 
    private String middleName; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 6) 
    @Column(name = "gender") 
    private String gender; 
    @Basic(optional = false) 
    @NotNull 
    @Column(name = "date_of_birth") 
    @Temporal(TemporalType.DATE) 
    private Date dateOfBirth; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 45) 
    @Column(name = "nationality") 
    private String nationality; 
    @Basic(optional = false) 
    @NotNull 
    @Column(name = "date_hired") 
    @Temporal(TemporalType.TIMESTAMP) 
    private Date dateHired; 
    @Size(max = 20) 
    @Column(name = "status") 
    private String status; 
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "staff") 
    private Collection<StaffApointments> staffApointmentsCollection; 
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "staff") 
    private StaffContact staffContact; 
    @JoinColumn(name = "account_id", referencedColumnName = "id") 
    @ManyToOne(optional = false) 
    private Account accountId; 
    @JoinColumn(name = "position_id", referencedColumnName = "id") 
    @ManyToOne(optional = false) 
    private Position positionId; 

    public Staff() { 
    } 

    public Staff(Integer id) { 
     this.id = id; 
    } 

    public Staff(Integer id, String lastName, String firstName, String gender, Date dateOfBirth, String nationality, Date dateHired) { 
     this.id = id; 
     this.lastName = lastName; 
     this.firstName = firstName; 
     this.gender = gender; 
     this.dateOfBirth = dateOfBirth; 
     this.nationality = nationality; 
     this.dateHired = dateHired; 
    } 

    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    public String getLastName() { 
     return lastName; 
    } 

    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 

    public String getFirstName() { 
     return firstName; 
    } 

    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 

    public String getMiddleName() { 
     return middleName; 
    } 

    public void setMiddleName(String middleName) { 
     this.middleName = middleName; 
    } 

    public String getGender() { 
     return gender; 
    } 

    public void setGender(String gender) { 
     this.gender = gender; 
    } 

    public Date getDateOfBirth() { 
     return dateOfBirth; 
    } 

    public void setDateOfBirth(Date dateOfBirth) { 
     this.dateOfBirth = dateOfBirth; 
    } 

    public String getNationality() { 
     return nationality; 
    } 

    public void setNationality(String nationality) { 
     this.nationality = nationality; 
    } 

    public Date getDateHired() { 
     return dateHired; 
    } 

    public void setDateHired(Date dateHired) { 
     this.dateHired = dateHired; 
    } 

    public String getStatus() { 
     return status; 
    } 

    public void setStatus(String status) { 
     this.status = status; 
    } 

    @XmlTransient 
    public Collection<StaffApointments> getStaffApointmentsCollection() { 
     return staffApointmentsCollection; 
    } 

    public void setStaffApointmentsCollection(Collection<StaffApointments> staffApointmentsCollection) { 
     this.staffApointmentsCollection = staffApointmentsCollection; 
    } 

    public StaffContact getStaffContact() { 
     return staffContact; 
    } 

    public void setStaffContact(StaffContact staffContact) { 
     this.staffContact = staffContact; 
    } 

    public Account getAccountId() { 
     return accountId; 
    } 

    public void setAccountId(Account accountId) { 
     this.accountId = accountId; 
    } 

    public Position getPositionId() { 
     return positionId; 
    } 

    public void setPositionId(Position positionId) { 
     this.positionId = positionId; 
    } 

    @Override 
    public int hashCode() { 
     int hash = 0; 
     hash += (id != null ? id.hashCode() : 0); 
     return hash; 
    } 

    @Override 
    public boolean equals(Object object) { 
     // TODO: Warning - this method won't work in the case the id fields are not set 
     if (!(object instanceof Staff)) { 
      return false; 
     } 
     Staff other = (Staff) object; 
     if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public String toString() { 
     return "entity.Staff[ id=" + id + " ]"; 
    } 

} 

Oto klasa Stanowisko także:

@Entity 
public class Position implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "id") 
    private Integer id; 
    @Basic(optional = false) 
    @NotNull 
    @Size(min = 1, max = 45) 
    @Column(name = "name") 
    private String name; 
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "positionId") 
    private Collection<Staff> staffCollection; 

    public Position() { 
    } 

    public Position(Integer id) { 
     this.id = id; 
    } 

    public Position(Integer id, String name) { 
     this.id = id; 
     this.name = name; 
    } 

    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    @XmlTransient 
    public Collection<Staff> getStaffCollection() { 
     return staffCollection; 
    } 

    public void setStaffCollection(Collection<Staff> staffCollection) { 
     this.staffCollection = staffCollection; 
    } 

    @Override 
    public int hashCode() { 
     int hash = 0; 
     hash += (id != null ? id.hashCode() : 0); 
     return hash; 
    } 

    @Override 
    public boolean equals(Object object) { 
     // TODO: Warning - this method won't work in the case the id fields are not set 
     if (!(object instanceof Position)) { 
      return false; 
     } 
     Position other = (Position) object; 
     if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public String toString() { 
     return "entity.Position[ id=" + id + " ]"; 
    } 

} 

EDIT 2:

dodałem @expose do atrybutów w moja klasa pracowników z wyjątkiem personelu. Ale wciąż mam 1 problem. Za każdym razem, gdy wybrana jest pierwsza wartość w liście rozwijanej (wartość = 1), nadal pojawia się błąd nieskończonej pętli. Czy ktoś może mi pomóc?

EDIT 3:

Naprawiono go! Dodałem ostateczny builder GsonBuilder = new GsonBuilder(); builder.excludeFieldsWithoutExposeAnnotation(); jako całość. Działa teraz

+0

Serwlet brzmi jak Java dla mnie, a twoje błędy dla sprawdzenia poprawności tej myśli ... może przydałoby się użycie tagu java? –

+0

Nie używaj w ogóle typu Raw, jak tutaj użyto 'Collection staffCollection', a następnie bez sprawdzania, czy jest konwertowane na ogólne' List'. * Prawdopodobnie stanie się, jeśli masz kołowy odnośnik. *, Który w wyniku analizy przechodzi do nieskończonej pętli. Udostępnij także klasy "Posiiton" i "Staff". – Braj

+0

@Braj moje klasy są generowane jako klasy encji z bazy danych. Tabela "Personel" odwołuje się do jej position_id z tabeli "Position". Wybaczcie mi, jeśli nie jestem w stanie was wyraźnie zrozumieć, jeśli chodzi o zbiór Zbiorów Pracowniczych, co byście zrobili? – MLDS

Odpowiedz

7

Problem polega na tym, że każdy Staff obiekt zawiera obiekt Pozycja że zawiera Collection z Staff obiektów, z których każdy zawiera Collection z Staff obiektów ponownie itd GSON będzie kontynuować chodzenie to drzewo na zawsze, bo to nigdy nie będzie przystanek .

Aby go rozwiązać, możesz zapoznać się z odpowiedziami na pytanie this.

+0

Dziękuję za przekierowanie mnie. Mam trochę problemów ze zrozumieniem, co eksponować. Czy powinienem wystawić pozycję positionID w klasie pracowników? Nadal daje mi błąd. Czy możesz wyjaśnić? – MLDS

+0

Nie powinieneś narażać wszystkich elementów z wyjątkiem tych, których nie chcesz w swoim JSON –

+0

Czy to wpłynie na moje operacje CRUD? – MLDS