Gute Software sollte sich an der entsprechenden Fachdomäne orientieren und nicht an der zugrundeliegenden Technologie. Um dies zu erreichen, wird allerdings eine Basis benötigt, die technisch ausgereift ist ohne Einschränkungen für die Entwicklung. Eine solche Basis kann mit dem Springframework geschaffen werden. Die Kombination von Spring, Annotations, Java Persistence (JPA) und Unit-Testing erlaubt eine flexible und modulare Architektur und könnte eine mögliche technische Basis für ein solches Softwaresystem sein.
Dieser Vortrag stellt einen Lösungsansatz anhand eines einfachen Beispiels vor. Die Aufbereitung der Inhalte orientiert sich dabei an einem typischen test-zentrierten Entwicklungsprozess. Folgende Themen werden angesprochen:
* Einleitung Spring und JPA, Maven, Groovy
* Projektstruktur
* Entwicklung der API (der Schnittstellen)
* Test-getriebene Entwicklung der Implementierung
* Spring-unterstützte Integrationstests
Ausblick:
* Spring 2.5 - mehr Annotations; Verwaltung von Entities mit Spring
* Webschicht - Anbindung einer Webanwendung mit Java Server Faces (JSF)
* Spring-Webservices - Contract-First Webservices mit Spring-WS 1.0
33. Exkurs: Spring [Was ist Spring?] Inversion of Control Ansammlung von API's Programmier- modell
34. Exkurs: Spring [Komponenten] Spring Core AOP Spring AOP AspectJ-Integration DAO Spring JDBC Transaction- Management ORM JPA Hibernate Toplink JDO JEE JMX JMS JCA Remoting EJB's Email WEB Spring MVC Struts WebWork Tapestry JSF PDF Portlets
47. Exkurs: Groovy The Groovy Truth Runtime type Evaluation criterion required for truth Boolean Booleanwert muss true sein Matcher Der reguläre Ausdruck muss mindestens 1 Treffer haben Collection Die Collection darf nicht leer sein Map Die Map darf nicht leer sein String Der String darf ebenfalls nicht leer sein Number Muss ungleich 0 sein Alles andere Die Objektreferenz muss ungleich null sein
48. Exkurs: Groovy – Listen und Ranges def list = [„item1“, „item2“, „item3“] assert list.size() def emptyList = [] assert !emptyList list << „item4“ assert list.size() == 4 def range = [1..4] assert range.size() == 4 def range1 = [1..<4] assert range1.size() == 3 Eine Liste mit 3 Einträgen Eine leere Liste Der ersten Liste wird ein Element hinzugefügt Eine Range mit den Werten 1, 2, 3, 4 wird erstellt Eine Range mit den Werten 1, 2, 3 wird erstellt
49. Exkurs: Groovy – Listen und Closures def list = [„item1“, „item2“, „item3“] list.each{ print it+“ „} > item1 item2 item3 assert list.find{it==„item2“} list = [„a1“, „a2“, „a3“, „i1“, „i2“] assert list.findAll{ it.startsWith(„i“)}.size() == 3 Each-Closure Ein bestimmtes Element finden Eine Anzahl an Elementen aus der Liste finden
50. Exkurs: Groovy - Maps def map = [key1: „value1“, key2: „value2“] assert map.size() == 2 assert map.key1 == „value1“ map.key3 == „value3“ assert map.size() == 3 assert map[„key2“] == „value2“ assert map.get(„key2“) == „value2“ def emptyMap = [:] assert !emptyMap Eine Map mit 2 Einträgen wird erstellt Ein 3. Eintrag wird hinzugefügt Alternative Zugriffsmethode auf die Elemente der Map Eine leere Map wird erstellt
56. Zum Beispiel: Impl - Entities @Entity(table=„CUSTOMERS“) public class Customer{ @Id @GeneratedValue( strategy = GenerationType.AUTO) private Long id; @OneToOne(targetEntity = Address.class, cascade = { CascadeType.ALL}) private IAddress address; @Column(length = 40) private String firstName; … } Entity auf Tabelle CUSTOMERS mappen Primary Key 1-zu-1 Beziehung Konfiguration einer Column in der Tabelle CUSTOMERS
57. Zum Beispiel: Impl – persistence.xml <persistence …> <persistence-unit name="spring2-jpa-basic-persistence-unit"> <properties> <property name="hibernate.jdbc.batch_size" value="0"/> <property name="hibernate.default_batch_fetch_size" value="5"/> […] </properties> </persistence-unit> </persistence> Eindeutiger Name der Persistence-Unit Eigenschaften der Persistence-Unit
58. Zum Beispiel: Impl – DAO‘s @Repository public class CustomerDao implements ICustomerDao { @PersistenceContext( unitName = "spring2-jpa-basic-persistence-unit") protected EntityManager entityManager; public List<ICustomer> findAll() { return entityManager .createQuery("from Customer c") .getResultList(); } […] } Sorgt für die Übersetzung von Exceptions Injection des Entity-Managers über Spring Plain Java
59. Zum Beispiel: Impl – Spring-Config <bean class=„PersistenceAnnotationBeanPostProcessor" /> <bean class=„PersistenceExceptionTranslationPostProcessor" /> Support der Annotations in den DAO‘s Excpetion Translation
65. Zum Beispiel: Problem Annotation @Service public class CustomerService{ @Autowired private ICustomerDao customerDao; } Spring-eigene Annotations @Target(value = ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Service public @interface MyService { } Eigene Annotation Basierend auf @Service @MyService public class CustomerService{ } Verwendung der eigenen Annotation
68. Zum Beispiel: Impl – Unit Testing public final void testChangeAddress() { IAddress expAddress = new Address( street: "s1", city: "c1", country: "c1", zipCode: "z1"); def addressDao = [ store:{entity -> expAddress}] as IAddressDao ICustomerService customerService = new CustomerService(addressDao: addressDao) def result = customerService .changeAddress(expAddress) assert expAddress == result } Erzeugung einer neuen Instanz mit Constructor- Enhancement Implementierung des IAddressDao Neue Instanz des ICustomerService Ausführen und Ergebnis vergleichen