JSF-EJB Best Practices

Diskutiere JSF-EJB Best Practices im Application Tier Forum; Hallo, ich habe mir eine Beispielanwendung erstellt, die mittels JSF Eingaben vom Benutzer holt und diese in eine Tabelle einträgt. Da ich kein...

  1. hyperion
    hyperion Neues Mitglied
    Hallo,

    ich habe mir eine Beispielanwendung erstellt, die mittels JSF Eingaben vom Benutzer holt und diese in eine Tabelle einträgt. Da ich kein Profi in dem Gebiet bin, wollte ich Euch mal fragen, wie man das am besten macht.

    Ich gehe einfach mal kurz den Weg von der Eingabe bis zur Tabelle durch:

    Auszug aus dem jsf. Drei einfache Eingabefelder. Die Daten werden in ein outcomeBean gespeichert und wenn man auf den Button drückt, wird die Methode addOutcome aufgerufen.
    HTML:

    <h:form>
                        <h:panelGrid columns="2">
                            <h:outputLabel for="category">Category:</h:outputLabel>
                            <h:inputText id="category" value="#{outcomeController.outcomeBean.category}"/>
                            <h:outputLabel for="value">Value:</h:outputLabel>
                            <h:inputText id="value" value="#{outcomeController.outcomeBean.value}"/>
                            <h:outputLabel for="description">Description:</h:outputLabel>
                            <h:inputText id="description" value="#{outcomeController.outcomeBean.description}"/>
                        </h:panelGrid>
                        <h:commandButton value="addOutcome" action="#{outcomeController.addOutcome}" />
                    </h:form>
    outcomeController ist ein CDI-Bean. und hat das outcomeBean als Attribut, welches im Konstruktor erzeugt wird(ob man das so macht?). outcomeEJB welche die eigentliche Logik implementiert wird mit @EJB injected. Die harte Navigation mit Rückgabe "index.xhtml" ist vermutlich nicht so gut.
    Code (Java):

    @Named
    @RequestScoped
    public class OutcomeController {
       
        @EJB
        private OutcomeEJB outcomeEJB;
        private OutcomeBean outcomeBean;
       
        public OutcomeController(){
            outcomeBean = new OutcomeBean();
        }

    ...
       
        public String addOutcome(){
            outcomeEJB.addOutcome(outcomeBean);
            return "index.xhtml";
        }
     
    outcomeBean ist ein POJO ohne jegliche Annotationen oder sonst was.
    Code (Java):

    public class OutcomeBean {
       
        private String category;
        private String description;
        private double value;

       //Setter und getter...    
    }
     
    Die EJB sieht dann wie folgt aus. Erzeugt eigentlich nur das @Entity-Objekt(Outcome), setzt die Werte und macht den Eintrag.
    Code (Java):

    @Stateless
    public class OutcomeEJB {

        @PersistenceContext
        private EntityManager em;
         
        public boolean addOutcome(OutcomeBean outcomeBean){
             Outcome outcome = new Outcome();
            outcome.setCategory(outcomeBean.getCategory());
            outcome.setDescription(outcomeBean.getDescription());
            outcome.setValue(outcomeBean.getValue());
            em.persist(outcome);
              return true;
        }
    }
     
    Outcome noch:
    Code (Java):

    @Entity
    @Table(name = "OUTCOME")
    @XmlRootElement
    @NamedQueries({
        @NamedQuery(name = "Outcome.findAll", query = "SELECT o FROM Outcome o"),
        @NamedQuery(name = "Outcome.findByOutcomeId", query = "SELECT o FROM Outcome o WHERE o.outcomeId = :outcomeId"),
        @NamedQuery(name = "Outcome.findByCategory", query = "SELECT o FROM Outcome o WHERE o.category = :category"),
        @NamedQuery(name = "Outcome.findByValue", query = "SELECT o FROM Outcome o WHERE o.value = :value"),
        @NamedQuery(name = "Outcome.findByDescription", query = "SELECT o FROM Outcome o WHERE o.description = :description")})
    public class Outcome implements Serializable {
       private static final long serialVersionUID = 1L;
           
        @Id
        @GeneratedValue
        @Basic(optional = false)
        @NotNull
        @Column(name = "OUTCOME_ID")
        private Integer outcomeId;
       
        @Basic(optional = false)
        @NotNull
        @Size(min = 1, max = 100)
        @Column(name = "CATEGORY")
        private String category;
       
        // @Max(value=?)  @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
        @Basic(optional = false)
        @NotNull
        @Column(name = "VALUE")
        private double value;
       
        @Size(max = 100)
        @Column(name = "DESCRIPTION")
        private String description;

        //getter und setter...
    }
     
    So also wo ich auch nicht so genau weiß, ob das so toll gelöst ist, ist dass Outcome und OutcomeBean nahezu gleich sind. Outcome hat eben noch die JPA Annotationen.

    Freue mich über jeden Tipp!

    Gruß,
    hyperion
     
  2. Vielleicht hilft dir dieser Kurs hier weiter --> (hier klicken)
  3. CptSocket
    CptSocket Mitglied
    Hallo hyperion

    Wenn ich die Snippets richtig verstanden habe sieht dein Beispiel etwa folgendermassen aus:
    Den Anhang 7166 betrachten

    Ich würde die folgenden Dinge anschauen:
    1. Naming:
      (Siehe Guidelines, Patterns, and code for end-to-end Java applications)
      Die Endung Bean wird normalerweise für SessionBeans verwendet (gemäss dem Link auch für Entity-Beans, da wird teilweise auch die Endung Entity oder ähnlich benützt).
      Transferobjekte (wie das OutcomeBean in deinem Beispiel) würde ich nicht mit Bean, sondern eher mit Dto, Vo, ... kennzeichnen (Siehe auch java - Difference between DTO, VO, POJO, JavaBeans? - Stack Overflow)
    2. Einsatz der Named Queries
      Was ist der Grund für die Named Queries in der Klasse Outcome?
      Alternative wäre Code ala
      Code (Java):
      public List<Outcome> ladeAlleOutcomes() {
          Criteria criteria = getHibernateSession().createCriteria(Outcome.class);
          List<Outcome> outcomes = criteria.list();
          return outcomes;
      }
      Je nach Anforderungen erweitert um Restriktionen oder ähnlich:
      Code (Java):
      criteria.add(Restrictions.eq("category", category));
      Vorteil von diesem Ansatz wäre, dass du kein oder weniger hql in den Klassen hast. (Der Entscheid zu HQL oder Criteria ist eher subjektiv, Criteria geht wahrscheinlich weniger schnell kaputt).
    3. In deinem Beispiel greifst du direkt aus dem Controller (Client) auf die Persistenz zu. Sobald die Applikation grösser wird, würde ich einen Service- und/oder einen Function/Logic-Layer reinziehen. Andernfalls besteht die Gefahr, dass die Applikation rasch unübersichtlich wird.
    4. Aus Sicht des Unittestings würde es sich anbieten, die Mapping-Logik der Methode OutcomeEjb.addOutcome() in einen Mapper auszulagern. Dann könntest du das Mappen der Objekte unabhängig von der Persistenzanbindung testen => bessere Testbarkeit der Applikation.


    Freundliche Grüsse
    CptSocket
     
Die Seite wird geladen...

JSF-EJB Best Practices - Ähnliche Themen

bestehendes Projekt als Applet speichern
bestehendes Projekt als Applet speichern im Forum Java Basics - Anfänger-Themen
Einfach verkettete Liste Element an bestimmter Position einfügen
Einfach verkettete Liste Element an bestimmter Position einfügen im Forum Java Basics - Anfänger-Themen
Nullstellen bestimmen
Nullstellen bestimmen im Forum Hausaufgaben
Min und Max einer Zahlenfolge bestimmen
Min und Max einer Zahlenfolge bestimmen im Forum Java Basics - Anfänger-Themen
ComboBox bestimmte Elemente disablen/ausgrauen
ComboBox bestimmte Elemente disablen/ausgrauen im Forum Java Basics - Anfänger-Themen
Thema: JSF-EJB Best Practices