Monat: Dezember 2009

GAE/J und Spring: Teil 2

Speichern von Daten per JDO

Als erstes werde ich mal die Domainenobjekte anlegen, in diesem Fall erstmal einen User und als 1:N die dazugehörigen WeightUnits, bestehend aus Gewicht/Tag. Außerdem benötigen wir noch die DAOs/Services sowie die PersistenceManagerFactory:

Für die Transaktionen muss noch die spring-tx.jar, spring-aop.jar und aopalliance-1.0.jar zum Classpath zugefügt werden.

Hier der User:

01@PersistenceCapable(identityType = IdentityType.APPLICATION)
02public class User implements Serializable
03{
04    @PrimaryKey
05    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
06    private Key key;
07 
08    @Persistent
09    private String j_username;
10 
11    @Persistent
12    private String j_password;
13 
14    @Persistent
15    private String email;
16 
17    @Persistent
18    private BigDecimal weight;
19 
20    @Persistent
21    private BigDecimal desiredWeight;
22 
23    @Persistent(mappedBy = "user")
24    private List<weightunit> weightUnits  = Lists.newArrayList();
25 
26//getter/setter
27}
28</weightunit>

Und die WeightUnit:

01@PersistenceCapable(identityType = IdentityType.APPLICATION)
02public class WeightUnit
03{
04    @PrimaryKey
05    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
06    private Key key;
07 
08    @Persistent
09    private Date day;
10 
11    @Persistent
12    private BigDecimal weight;
13 
14    @Persistent
15    private User user;
16 
17//getter/setter
18 
19}

In der application-context.xml wird die PersistenceManagerFactory verdrahtet:

01<tx:annotation-driven>
02    <bean id="persistenceManagerFactory" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
03<property name="persistenceManagerFactoryName" value="transactions-optional">
04    </property>
05 
06    <bean id="transactionManager" class="org.springframework.orm.jdo.JdoTransactionManager">
07<property name="persistenceManagerFactory" ref="persistenceManagerFactory">
08    </property>
09 
10    <bean id="userDAO" class="de.pmannel.login.UserDAOImpl">
11<property name="persistenceManagerFactory" ref="persistenceManagerFactory">
12    </property>
13 
14    <bean id="userService" class="de.pmannel.login.UserServiceImpl">
15<property name="userDAO" ref="userDAO">
16    </property>
17</bean></bean></bean></bean></tx:annotation-driven>

anschließend benötigen wir die DAOs zum Speichern und Auslesen. Zu jeder DAOImpl gehört natürlich ein Interface, welches ich aus Platzgründen weg lasse:

01public class UserDAOImpl extends JdoDaoSupport implements UserDAO
02{
03 
04    @Override
05    public void delete(User user)
06    {
07        // TODO Auto-generated method stub
08 
09    }
10 
11    @Override
12    public User findUserById( Key key)
13    {
14        // TODO Auto-generated method stub
15        return null;
16    }
17 
18    @Override
19    public User save(User user)
20    {
21            return getPersistenceManager().makePersistent(user);
22    }
23 
24}

Ich verwende hier den JdoDaoSupport und binde mich damit an Spring, wer möchte kann sich die Factory auch selber injecten.

Anschließend noch Service/ServiceImpl erzeugen und in einen Controller injecten.

Damit die Session während eines Views nicht geschlossen werden, kommt noch ein OpenPersistenceInViewFilter in die web.xml.

1<filter>
2    <filter-name>OpenPersistenceManagerInViewFilter</filter-name>
3    <filter-class>org.springframework.orm.jdo.support.OpenPersistenceManagerInViewFilter</filter-class>
4</filter>
5<filter-mapping>
6    <filter-name>OpenPersistenceManagerInViewFilter</filter-name>
7    <url-pattern>/*</url-pattern>
8</filter-mapping>

Im nächsten Teil versuche ich dann, Spring Security in der Anwendung zum Laufen zu bekommen.




GAE/J und Spring: Teil 1

Aufsetzen eines GAE/J-Projekts

Download und Installation des Google App Engine SDK: SDK
Außerdem natürlich das Plugin für Eclipse: Plugin

Dann ein neues Web Application Project anlegen, dabei aber den Haken bei “Use Google Web Toolkit” rausnehmen
Anlegen

Als nächstes die Spring Libraries hinzufügen:

  • spring-core.jar
  • spring-beans.jar
  • spring-context.jar
  • spring-web.jar
  • spring-webmvc.jar
  • jstl.jar
  • standard.jar
  • commons-logging.jar

Auf keinen Fall die All-In-One spring.jar benutzen, da javax.naming.* von GAE nicht unterstützt wird.

Spring Security lasse ich vorerst weg!

Als nächstes in der web.xml das Dispatcher-Servlet bekanntmachen:

01<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/j2ee" version="2.4">
02 
03    <servlet>
04        <servlet-name>dispatcher</servlet-name>
05        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
06        <load-on-startup>1</load-on-startup>
07    </servlet>
08 
09    <servlet-mapping>
10        <servlet-name>dispatcher</servlet-name>
11        <url-pattern>*.html</url-pattern>
12    </servlet-mapping>
13 
14    <!-- Loads the Spring-Context.xml -->
15<listener>
16<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
17    </listener>
18    <context-param>
19<param-name>contextConfigLocation</param-name>
20<param-value>
21            WEB-INF/application-context.xml
22            </param-value>
23    </context-param>
24 
25    <welcome-file-list>
26        <welcome-file>index.jsp</welcome-file>
27    </welcome-file-list>
28</web-app>

Achtung: Wer El/JSTL benutzen möchte, sollte die 2.4 Version im Schema verwenden, oder ElIgnored in der JSP auf false setzen!

Ich habe auch schon für später eine application-context.xml in der web.xml angelegt!

Eine JSP mit Formular, um sich anzumelden:

01<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
02<%@ include file="/jsp/include.jsp"%>
03 
04 
05 
06<form:form commandname="Login" method="post">
07<table>
08<tbody><tr>
09<td>Username</td>
10<td>
11<form:input path="j_username"></form:input></td>
12</tr>
13<tr>
14<td>Passwort</td>
15<td>
16<form:password path="j_password"></form:password></td>
17</tr>
18<tr>
19<td colspan="2">
20<input value="Absenden" type="submit"></td>
21</tr>
22</tbody></table>
23</form:form>

Der dazugehörende Controller:

01package de.<b style="color: black; background-color: rgb(160, 255, 255);">pmannel</b>.login;
02 
03import javax.servlet.http.HttpServletRequest;
04import javax.servlet.http.HttpServletResponse;
05 
06import org.springframework.validation.BindException;
07import org.springframework.web.servlet.ModelAndView;
08import org.springframework.web.servlet.mvc.SimpleFormController;
09import org.springframework.web.servlet.view.RedirectView;
10 
11public class LoginController extends SimpleFormController
12{
13 
14    @Override
15    protected ModelAndView onSubmit(HttpServletRequest request,
16            HttpServletResponse response, Object command, BindException errors)
17            throws Exception
18    {
19        ModelAndView mv = new ModelAndView(new RedirectView(getSuccessView()));
20 
21        User user = (User)command;
22        mv.addObject("username",user.getJ_username());
23        return mv;
24    }
25}

Die Jsp, an die gepostet wird:

1<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
2<%@ include file="/jsp/include.jsp"%>
3 
4hi <c:out value="${username}">!
5</c:out>

Der Controller dafür:

01package de.<b style="color: black; background-color: rgb(160, 255, 255);">pmannel</b>.login;
02 
03import javax.servlet.http.HttpServletRequest;
04import javax.servlet.http.HttpServletResponse;
05 
06import org.springframework.web.bind.ServletRequestUtils;
07import org.springframework.web.servlet.ModelAndView;
08import org.springframework.web.servlet.mvc.Controller;
09 
10public class MyAppController implements Controller
11{
12 
13    @Override
14    public ModelAndView handleRequest(HttpServletRequest arg0,
15            HttpServletResponse arg1) throws Exception
16    {
17        ModelAndView mv = new ModelAndView("myapp");
18 
19        mv.addObject("username",ServletRequestUtils.getStringParameter(arg0, "username"));
20 
21        return mv;
22    }
23}

und meine Dispatcher-Servlet.xml:

02 
04 
06 
08 
10 
12 
14 
16 
17    <bean id="defaultHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
18<property name="order" value="0">
19<property name="alwaysUseFullPath" value="true">
20<property name="mappings">
21<props>
22<prop key="/login.html">loginController</prop>
23<prop key="/secure/myapp.html">myAppController</prop>
24        </props>
25        </property>
26    </property>
27 
28    <bean id="loginController" class="de.pmannel.login.LoginController">
29<property name="commandClass" value="de.pmannel.login.User">
30<property name="commandName" value="Login">
31<property name="formView" value="login">
32<property name="successView" value="secure/myapp.html">
33    </property>
34 
35    <bean id="myAppController" class="de.pmannel.login.MyAppController"></bean>
36 
37    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
38<property name="prefix" value="/jsp/">
39<property name="suffix" value=".jsp">
40    </property>
41 
42</property></bean></property></property></property></bean></property></bean></beans>

in der include.jsp kommen folgende Taglibs:

1<%@ taglib prefix="c"            uri="http://java.sun.com/jsp/jstl/core" %>
2<%@ taglib prefix="fmt"      uri="http://java.sun.com/jsp/jstl/fmt" %>
3<%@ taglib prefix="spring"       uri="http://www.springframework.org/tags" %>
4<%@ taglib prefix="form"         uri="http://www.springframework.org/tags/form" %>

Wenn dann alles soweit fertig ist, rechte Maustaste auf das Projekt, Run As –> Web Application!

Damit läuft GAE/J schonmal mit Spring MVC! Als nächstes versuche ich, mit Spring ORM und JDO den User im DataStore zu speichern.