ich sitze an einer Anwendung in der ein Benutzer eine Maske ausfüllen kann, welche durch die Werte einer Bean vorgegeben ist. Wenn diese Maske ausgefüllt ist, sollen diese Daten irgendwie gespeichert werden. Ist der Benutzer fertig sollen alle Einträge in einer XML-Datei zusammengefasst werden. Mein Problem ist es aber gerade zu verstehen wie ich am besten die Eingaben temporär speichern kann um sie z.B. auch direkt in einer Tabelle anzeigen zu können.
Meine Idee war es 2 Klassen zu erstellen, einmal die Bean und dann eine Klasse die einfach eine Liste dieser Beans vorhält. Nur wie kriege ich dann ein Bean-Objekt in die Klasse mit der Liste um diese dort zu speichern? Eine Bean mit diesen Werten zu füllen ist kein Problem. Aber diese Werte dann eben nicht aus dieser Klasse heraus wegzuspeichern sondern in einer anderen Klasse zu verwenden bereit mir gerade Kopfzerbrechen. Hat da jmd ein Stichwort für mich? Ich bin doch bestimmt nicht der erste der reine Daten-Beans irgendwo speichern will.
Beispiel Bean:
@Named
@Stateless
public class meine Bean {
//private vars
//getter und setter
}
SpeicherKlasse:
@Named
@SessionScoped
public class meineBeanListe {
//private List<Beans>
//getter und setter
public void save(???) //<--- hier müsste die Bean rein
}
Im Prinzip ist Deine Klasse “MeineBeanListe” (Klassen immer Groß!) doch nur ein Wrapper um eine java.util.List. Mach doch einfach eine add-Methode, so wie sie java.util.List anbietet.
Ich bin jetzt etwas weiter. @nillehammer : Ich kann einer Methode keine params/Bean übergeben meines Wissens. Klassen hab ich natürlich groß
Es funktioniert wenn ich eine private Bean-Variable mittels @Inject injiziere. Jetzt habe ich allerdings das Problem, dass ich bei jedem „add“ in die Liste immer das gleiche Objekt mit aktuellen Werten hinzufüge. Da ich die ganze Zeit auf der gleichen Xhtml-Setie bleibe und die Tabelle mit den eingegebenen Beans per AJax aktualisiere findet auch kein Refresh statt. Jetzt habe ich temporär in der add-Methode eine Bean angelegt und die Werte der Klassenvariable kopiert. Ist natürlich irgendwie unschön dann doch wieder mit dem new Operator. Ich denke es liegt am Scope. Da ich mit CDI arbeiten möchte fällt @ViewScope flach und würde auch nicht viel bringen da die Seite ja nicht komplett aktualisiert wird. Ich sitze aber dran aber falls jmd wieder ein Stichwort hat…immer her damit
Ausschnitt:
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import java.util.List;
import java.util.ArrayList;
import javax.inject.Inject;
import java.io.Serializable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author tim
*/
@Named("formularcontroller")
@SessionScoped
public class FormularController implements Serializable {
@Inject
private FormularBean bean;
public void add(){
//FormularBean tmp = new... <-- andere Möglichkeit?:(
//copy....
//add Entries...
}
Also ich habe das mit den Beans so verstanden, dass ein Bean quasi hinter einer View (.xhtml) liegt. Der Bean stellt die Daten für die View bereit und ist dafür zuständig die Benutzereingaben entsprechend aus zu werten und die notwendigen Schritte auszuführen (Z.B. Benutzer klick auf Save -> Bean fängt Ereignis ab und sammelt die eingegebenen Daten ein und reicht sie ans Model weiter und sagt, bitte speichere mir das in die DB).
Alles andere, also wie die Daten aussehen, gespeichert und verarbeitet werden, gehören in die Buissnes Logik. Ein Bean in einem Bean ergibt somit für mich keinen Sinn.
In deinem Fall müsstest du eine Klasse erstellen um die Daten zu speichern. Z.B. Klasse Person mit den nötigen Eigenschaften. Je nach dem kannst du dann nochmal eine Klasse machen, die dafür zuständig ist die Klasse Person zu laden oder zu speichern.
In der Bean Klasse in der die add Methode ist, müsstest du jetzt quasi eine Klasse Person erstellen und diese dann entsprechend speichern.
Bitte korrigiert mich wenn ich das mit dem Bean und dem Model falsch verstanden habe!
Das ist schon in etwa korrekt, wenn ICH das richtig verstanden habe
Ich habe also eine View-Bean die 1zu1 einer JSF Seite entspricht. Wenn diese View-Bean gefüllt ist soll diese aber nicht direkt in einer DB landen sondern eben in einer Klasse die diese Beans verwaltet. Somit kann ich z.B. durch alle Eingaben navigieren und der Benutzer kann z.B. ein Feld einer Bean ändern.
Die Daten sollen aber auch niemals in einer Datenbank laden, weil du im Eingangspost was von XML erwähnt hast, gehe ich davon aus, dass dein Vorgehen das ist, dass du erstmal alle Daten sammelst und sie dann per XML verschickst ? Richtig?
Hab mich direkt noch nicht soviel mit CDI beschäftigt aber ich schaue nachher mal…
HI @pl4gu33 Die Daten sollen im Anschluss an einen Webservice geschickt werden, der die Daten weiter verarbeitet und dann irgendwie persistiert. Allerdings erst wenn der Benutzer alle Eingaben getätigt hat. Mein Vorhaben war die Persistierung per XML und darauf aufbauend eine View in der die verarbeiteten Eingaben angeschaut werden können. Ob diese View aus einem XML kommt oder einer DB ist noch nicht entschieden.
Also ich hab dir mal ein Beispiel via Primefaces + CDI gebaut. Würde halt nur noch der Sendebutton für das XML fehlen.
Ich bin mir da nicht sicher, ob es so schlimm ist, hier den „new“ Operator zu benutzen. Ich denke, das is durch aus legitim, aber lasse mich gern überzeugen, hab noch net allzu viel mit CDI gemacht. Ansonsten mal in die Richtung Producer gehen.
Vielleicht kannst du damit ja was anfangen
(PS die Checks hab ich mal weggelassen)
(PS2 und natürlich sollte man nicht den gleichen Namen vergeben wegen der ROW ID ;))
Bean:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.faces.event.ActionEvent;
import javax.inject.Named;
@SessionScoped
@Named(value="tableBean")
public class TableBean implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private List<Person> personList;
private Person selectedPerson;
@PostConstruct
public void init(){
personList = new ArrayList<Person>();
personList.add(new Person("Hans", "Hamburg", 33));
personList.add(new Person("Karl", "Kiel", 55));
}
public void savePerson(ActionEvent event){
personList.add(selectedPerson);
}
public boolean isNewPerson(){
return personList.contains(selectedPerson);
}
public void reset(ActionEvent event){
selectedPerson = null;
}
public void preparePerson(ActionEvent event){
selectedPerson = new Person();
}
/**
* Getter Setter
* @return
*/
public List<Person> getPersonList() {
return personList;
}
public void setPersonList(List<Person> personList) {
this.personList = personList;
}
public Person getSelectedPerson() {
return selectedPerson;
}
public void setSelectedPerson(Person selectedPerson) {
this.selectedPerson = selectedPerson;
}
}
XHTML:
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form id="tableform">
<p:dataTable value="#{tableBean.personList}" var="person"
selection="#{tableBean.selectedPerson}" selectionMode="single"
rowKey="#{person.name}">
<p:ajax event="rowSelect" update="@form" />
<p:ajax event="rowUnselect" update="@form" />
<p:column>
<f:facet name="header">Name</f:facet>
#{person.name}
</p:column>
<p:column>
<f:facet name="header">Ort</f:facet>
#{person.ort}
</p:column>
<p:column>
<f:facet name="header">Alter</f:facet>
#{person.alter}
</p:column>
<f:facet name="footer">
<p:commandButton value="Erstellen"
actionListener="#{tableBean.preparePerson}"
oncomplete="dialog.show()" update=":dialogform" />
<p:commandButton value="Bearbeiten"
disabled="#{tableBean.selectedPerson == null}"
oncomplete="dialog.show()" update=":dialogform"/>
</f:facet>
</p:dataTable>
</h:form>
<p:dialog widgetVar="dialog">
<h:form id="dialogform">
<p:inputText value="#{tableBean.selectedPerson.name}" />
<p:inputText value="#{tableBean.selectedPerson.ort}" />
<p:inputText value="#{tableBean.selectedPerson.alter}" />
<p:commandButton value="Speichern"
actionListener="#{tableBean.savePerson}"
rendered="#{!tableBean.newPerson}"
oncomplete="dialog.hide()" update=":tableform"/>
<p:commandButton value="Speichern" rendered="#{tableBean.newPerson}"
oncomplete="dialog.hide()" update=":tableform"/>
<p:commandButton value="Cancel"
actionListener="#{tableBean.reset}"
oncomplete="dialog.hide()" />
</h:form>
</p:dialog>
</h:body>
</html>```
```package bean;
import java.io.Serializable;
public class Person implements Serializable{
private String name;
private int alter;
private String ort;
public Person(String name, String ort, int alter){
this.name = name;
this.ort = ort;
this.alter = alter;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAlter() {
return alter;
}
public void setAlter(int alter) {
this.alter = alter;
}
public String getOrt() {
return ort;
}
public void setOrt(String ort) {
this.ort = ort;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + alter;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((ort == null) ? 0 : ort.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (alter != other.alter)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (ort == null) {
if (other.ort != null)
return false;
} else if (!ort.equals(other.ort))
return false;
return true;
}
}
Danke @pl4gu33 , ich schau mir das an, werde aber wohl erst am Mittwoch dazu kommen. PF nutze ich auch, sieht bisher auch recht ähnlich aus wobei ich die Person noch als Bean definiere…vll. sollte ich das einfach mal lassen
Was mir gerade noch aufgefallen ist. Das ist teilweise schon ganz nützlich wenn man dazu dann " @ManagedProperty(„#{beanname}“)" benutzt, kann man zum Beispiel in einer View/Request- Scope Bean die Daten aus einer Session/Application- Bean ziehen.