Re: Generating ActionForms & Retrieving DataContexts (updated)

From: Mike Kienenberger (mkienen..laska.net)
Date: Fri Jul 02 2004 - 12:34:14 EDT

  • Next message: Jonathan Carlson: "Re: flattened relationships"

    I think Scott meant this message to go to the mailing list since it's
    primarily about his DataContextProvider.

    Begin forwarded message:

    Date: Fri, 02 Jul 2004 03:32:58 -0400
    From: Scott McClure <scot..martblob.com>
    Subject: Re: Generating ActionForms & Retrieving DataContexts (updated)
    In-reply-to: <0407011340.AA571093..avilion>
    To: Mike Kienenberger <mkienen..laska.net>
    Message-id: <40E50FAA.902060..martblob.com>

    Hmmm... This sounds very helpful! It will have to wait until when I get
    back from vacation (I am not ignoring you, hehe).

    Now, for something completely different.

    Anyways, some of you might remember a release of my DataContextProvider
    last week. Hopefully none of you tried to compile it (blush). I recieved
    just punishment for not even compiling - non-existant variables, missing
    brackets... It sucked. Well, version beta is here (it still hasnt been
    functionally tested...). At least this one compiles.

    My vacation also means that any emails will be going unanswered for two
    weeks, so be in peace, and look around for documentation on sessions in
    Hibernate and ThreadLocal if you really need information on the
    DataContextProvider. From a few different implementations of that
    pattern, I built this.

    Scott

    Mike Kienenberger wrote:

    >Scott McClure <scot..martblob.com> wrote:
    >
    >
    >>I was wondering how simple it would be to extend the current DataObject
    >>generation tasks/interface to allow to create ActionForms as well.
    >>
    >>
    >ActionForms
    >
    >
    >>are Struts classes that closely mirror the model classes. Even if they
    >>
    >>
    >would
    >
    >
    >>need to be edited (validation added, fields removed, etc.), It would be
    >>
    >>
    >much
    >
    >
    >>nicer to have a chance to build the initial files from Cayenne.
    >>
    >>All that is needed from Cayenne is to run one more Velocity template.
    >>
    >>
    >
    >Take a look at this for the patches.
    >
    >http://objectstyle.org/jira/secure/ViewIssue.jspa?key=CAY-79
    >
    >Then you can do things like the following. I have templates for
    >validation.xml and for *Action.java as well.
    >
    >
    >
    ============================================================================
    >
    >
    > <!-- Rebuild classes dependent on database model -->
    >
    > <target name="generateEditEntityPart4" depends="init"
    >description="cmd-line: Generates EditENTITYEntity-struts-config.xml">
    >
    > <taskdef name="cgen"
    >classname="org.objectstyle.cayenne.tools.CayenneGenerator">
    >
    > <classpath refid="generate.classpath"/>
    >
    > </taskdef>
    >
    > <cgen
    >map="${local.project.location}/Ebpp-struts/WEB-INF/OnlineBilling.map.xml"
    >
    > filenamePrefix="Edit"
    >
    > filenameSuffix="Entity-struts-config.xml"
    >
    > entity="${ENTITY_NAME}"
    >
    > overwrite="false"
    >
    >
    >destDir="${local.project.location}/Ebpp-struts/WEB-INF/pages/generated"
    >
    > makepairs="false"
    >
    >
    >
    template="${local.project.location}/Ebpp-struts/WEB-INF/src/support/VelocityEditEntityComponent/VelocityEditEntityComponent.struts-

    >config.vm"
    >
    > usepkgpath="false"
    >
    > />
    >
    > </target>
    >
    >
    >
    >
    ============================================================================
    >
    >
    >#set( $dollarSign = '$' )
    >
    >#set( $poundSign = '#' )
    >
    >#set( $CapitializedEntityName =
    >${classGen.capitalizeString($classGen.Entity.name)})
    >
    >#set( $unCapitializedEntityName =
    >${classGen.uncapitalizeString($classGen.Entity.name)})
    >
    ><?xml version="1.0" encoding="ISO-8859-1" ?>
    >
    >
    >
    ><!DOCTYPE struts-config PUBLIC
    >
    > "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
    >
    > "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
    >
    ><struts-config>
    >
    >
    >
    > <form-beans>
    >
    >
    >
    > <form-bean
    >
    > name="edit${CapitializedEntityName}EntityForm"
    >
    >
    >type="org_apache_struts_validator.NullConvertingDynaValidatorForm">
    >
    >#foreach ( $attribute in $classGen.Entity.Attributes )##
    >
    >#set ($capitalizedAttribute =
    >${classGen.capitalizeString($attribute.name)})##
    >
    >#set ($uncapitalizedAttribute =
    >${classGen.uncapitalizeString($attribute.name)})##
    >
    >#if ($attribute.Type == "java.lang.Boolean")##
    >
    > <form-property
    >
    > name="$uncapitalizedAttribute"
    >
    > type="java.lang.Boolean"/>
    >
    >#else## ($attribute.Type == "java.lang.Boolean")##
    >
    > <form-property
    >
    > name="$uncapitalizedAttribute"
    >
    > type="java.lang.String"/>
    >
    >#end## ($attribute.Type == "java.lang.Boolean")##
    >
    >#end## ( $attribute in $classGen.Entity.Attributes )
    >
    > </form-bean>
    >
    >
    >
    >
    >
    > </form-beans>
    >
    >
    >
    > <action-mappings>
    >
    >
    >
    > <action path="/Edit${CapitializedEntityName}Entity"
    >
    >
    >
    type="com.gvea.struts.ebpp.action.generated.InitializeEdit${CapitializedEntityName}EntityAction"
    >
    > scope="request"
    >
    > name="edit${CapitializedEntityName}EntityForm"
    >
    > validate="false"
    >
    > input="/vm/Edit${CapitializedEntityName}Entity.do">
    >
    > <forward name="Success"
    >path="/vm/Edit${CapitializedEntityName}Entity.do"/>
    >
    > </action>
    >
    >
    >
    > <action path="/Edit${CapitializedEntityName}EntityResult"
    >
    >
    >
    type="com.gvea.struts.ebpp.action.generated.Edit${CapitializedEntityName}EntityAction"
    >
    > scope="request"
    >
    > name="edit${CapitializedEntityName}EntityForm"
    >
    > validate="true"
    >
    > input="/vm/Edit${CapitializedEntityName}Entity.do">
    >
    > <forward name="Success"
    >path="/vm/Edit${CapitializedEntityName}Entity.do"/>
    >
    > <forward name="Failure"
    >path="/vm/Edit${CapitializedEntityName}Entity.do"/>
    >
    > </action>
    >
    >
    >
    >
    >
    > <action path="/vm/Edit${CapitializedEntityName}Entity"
    >
    > type="us_ok_deq_wqdata.http.ViewAction"
    >
    > validate="false"
    >
    >
    >
    parameter="IsExternal;ShouldShowReturnToLastPageLink;Title;leftSideMenu;loginPanel;header;body;footer">

    >
    >
    > <forward name="IsExternal" path="false" />
    >
    > <forward name="Title" path="Golden Valley Electric Association -
    Online
    >Bill Payment - Edit ${CapitializedEntityName}" />
    >
    > <forward name="body"
    >path="/WEB-INF/pages/generated/Edit${CapitializedEntityName}Entity.vm" />
    >
    > </action>
    >
    >
    >
    > </action-mappings>
    >
    >
    >
    ></struts-config>
    >
    >
    >
    >
    ============================================================================
    >
    >
    >
    >
    >
    >

    /*
     * Created on Jun 30, 2004
     */
    package com.bandsbars.dao.cayenne;

    import org.objectstyle.cayenne.access.DataContext;
    import org.objectstyle.cayenne.conf.BasicServletConfiguration;
    import org.objectstyle.cayenne.conf.WebApplicationListener;

    import javax.servlet.ServletRequest;
    import javax.servlet.ServletRequestEvent;
    import javax.servlet.ServletRequestListener;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;

    /**
     * <p>
     * This class allows for a web application to retrieve a DataContext
    anywhere in
     * a servlet request. This is very useful when you want to decouple the
     * controller layer (Servlets, Struts, etc.) from a DAO layer, and
    cannot/should
     * not include a implementation-specific DataContext in a DAO interface. To
    use
     * this class, configure this class as a listener (like the
     * WebApplicationListener):
     * </p>
     * <p>
     * In <code>web.xml</code> deployment descriptor, configure as a listener of
     * context, session, and request events:
     * </p>
     *
     * <pre>
     *
     * &lt;listener&gt;
     *
    &lt;listener-class&gt;org.objectstyle.cayenne.conf.WebApplicationListener&lt;/listener-
    class&gt;
     * &lt;/listener&gt;
     *
     * </pre>
     *
     * You then can retrieve a DataContext by calling the static method
     * ..ink DataContextProvider#getDataContext()}or by calling
     * ..ink BasicServletConfiguration#getDefaultContext(HttpSession)}
     * <p>
     * <b>If using DataContextProvider, do not include a WebApplicationListener
    as
     * well. </b>
     * </p>
     * <p>
     * This class relies on the new functionality from Servlet 2.4 API (Tomcat
    5.*).
     * </p>
     *
     *..uthor <a href="mailto:scott@smartblob.com">Scott McClure </a>
     */
    public class DataContextProvider extends WebApplicationListener implements
                    ServletRequestListener {
            protected static ThreadLocal dataContext = new ThreadLocal();

            /*
             * <p> Given a request, get the DataContext from the Session, and bind the
             * DataContext to the thread. </p>
             */
            public void requestInitialized(ServletRequestEvent sre) {
                    ServletRequest req = sre.getServletRequest();

                    if (req instanceof HttpServletRequest) {
                            HttpSession session = ((HttpServletRequest) req).getSession();
                            DataContext dc = (DataContext) session
                                            .getAttribute(BasicServletConfiguration.DATA_CONTEXT_KEY);
                            if (dc != null) {
                                    dataContext.set(dc);
                            } else {
                                    throw new IllegalStateException("DataContext is null for the session,
    cannot bind to thread.");
                            }
                    }
            }

            /*
             * Remove the reference to the DataContext from the thread.
             */
            public void requestDestroyed(ServletRequestEvent sre) {
                    //Prevent lingering object references
                    dataContext.set(null);
            }

            /*
             * <p> Return the DataContext for this request. </p><p> <b>ONLY CALL THIS
             * METHOD FROM WITHIN THE CONTEXT OF A REQUEST! </b> </p>..eturns the
             * DataContext associated with this thread.
             */
            public static DataContext getDataContext() {
                    DataContext dc = (DataContext) dataContext.get();

                    if (dc == null) {
                            throw new IllegalStateException(
                                            "DataContextProvider.get() has been called outside the thread
    associated with a servlet request.");
                    }

                    return dc;
            }
    }



    This archive was generated by hypermail 2.0.0 : Fri Jul 02 2004 - 12:34:05 EDT