|
From: Aliaksandr R. <ara...@gm...> - 2004-12-30 14:20:31
Attachments:
Simple.java
|
Hello everybody, you got it right - Yet Another Web Framework ;)
Everybody loves writing web frameworks, so I do ;)))
My idea is to annotate POJOs, their methods and arguments with metadata
to make them web request handlers. I’ve never heart of this approach
before, correct me if I’m wrong. Let me explain it in details, let’s
start from example. Take a look at the following snippets of code, pay
your attention to the javadocs:
Here is declaration of a POJO whose methods will handle web requests:
/**
* Simple action handler, defines default view name for the action
* methods that don't specify their own ones.
*
* @@web.extensions.ActionSet(defaultViewName="default")
*/
public class Simple {
...
Here is the method which would handle requests to "/welcome.htm":
/**
* The simplest method ever, it does not take any parameters nor
* does it return anything. Returned view name is taken from class
* annotation.
*
* @@web.extensions.ActionHandler("/welcome")
*/
public void welcome() {
// custom code goes here
}
Here is the method whose arguments are taken from request values.
/**
* A more advanced example. Method's arguments are taken from the
* corresponding request's values. Here the <em>userId</em>
* argument is taken from the <em>uid</em> request's parameter
* converted to integer. If none is specified then default value is
* choosen. The <em>username</em> and <em>password</em> arguments
* are mandatory.
*
* @@web.extensions.ActionHandler("/simple/dummylogin")
* @@.userId web.extensions.ActionParam("uid", defaultValue=0)
* @@.email web.extensions.ActionParam("eml", required=true)
* @@.password web.extensions.ActionParam("pwd", required=true)
*/
public ModelAndView dummylogin(int userId, String email, String password) {
// login code goes here
Map model = new HashMap();
model.put("message", "Login successful");
return new ModelAndView("default", "model", model);
}
And fragment of the configuration code:
<!--
- This bean is an explicit URL mapper that is used by the dispatcher
- servlet.
- It is used instead of the default BeanNameUrlHandlerMapping.
-->
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/**/*.htm">controller</prop>
</props>
</property>
</bean>
<!--
- A POJO whose methods will handle web requests.
-->
<bean id="simple" class="web.extensions.simple.Simple">
</bean>
<!--
- A Controller dispatching web requests to a POJO.
-->
<bean id="controller" class="web.extensions.ActionSetController">
<property name="actionSet">
<ref local="simple"/>
</property>
</bean>
From my experience complex web applications always have large number of
methods processing web requests. The methods have to deal with web
request parameters, but they don’t have to handle user form submissions
and don’t require data validation. For example, a server script would
generate an URL which clicked by user would change web application state
somehow. Building separate Command objects for every controller method
would be overkill, dealing with servlet’s parameter maps is annoyance.
This is where metadata comes to help. I believe the example code above
is a small piece of what can be done with attributes, they can solve
wider range of problems of web applications.
I’ve written initial working demo, which is in alpha state now. As
youmay guess it is Spring’s AbstractController implementation. I used
Apache commons-attributes, because of their compatibility with JDK1.4,
but JDK1.5 annotations are also possible.
I’d like to ask the community, what do you think about the idea? Do you
lake it? Does it have any future? Is so, may be it isthe time to
implement it in some framework? I would appreciate any feedback from you.
Thanks, Alex.
PS
Happy New 2005 Year!!!
|
|
From: Steven D. <ste...@gm...> - 2004-12-30 16:13:14
|
Hi Aliaksandr,
Looks nice. Does this framework have a name or shall I just refer to
it as YAWF? :-)
Can we download a distribution somewhere?
Steven
On Thu, 30 Dec 2004 16:11:00 +0200, Aliaksandr Radzivanovich
<ara...@gm...> wrote:
> Hello everybody, you got it right - Yet Another Web Framework ;)
> Everybody loves writing web frameworks, so I do ;)))
> My idea is to annotate POJOs, their methods and arguments with metadata
> to make them web request handlers. I've never heart of this approach
> before, correct me if I'm wrong. Let me explain it in details, let's
> start from example. Take a look at the following snippets of code, pay
> your attention to the javadocs:
>
> Here is declaration of a POJO whose methods will handle web requests:
>
> /**
> * Simple action handler, defines default view name for the action
> * methods that don't specify their own ones.
> *
> * @@web.extensions.ActionSet(defaultViewName="default")
> */
> public class Simple {
> ...
>
> Here is the method which would handle requests to "/welcome.htm":
>
> /**
> * The simplest method ever, it does not take any parameters nor
> * does it return anything. Returned view name is taken from class
> * annotation.
> *
> * @@web.extensions.ActionHandler("/welcome")
> */
> public void welcome() {
> // custom code goes here
> }
>
> Here is the method whose arguments are taken from request values.
>
> /**
> * A more advanced example. Method's arguments are taken from the
> * corresponding request's values. Here the <em>userId</em>
> * argument is taken from the <em>uid</em> request's parameter
> * converted to integer. If none is specified then default value is
> * choosen. The <em>username</em> and <em>password</em> arguments
> * are mandatory.
> *
> * @@web.extensions.ActionHandler("/simple/dummylogin")
> * @@.userId web.extensions.ActionParam("uid", defaultValue=0)
> * @@.email web.extensions.ActionParam("eml", required=true)
> * @@.password web.extensions.ActionParam("pwd", required=true)
> */
> public ModelAndView dummylogin(int userId, String email, String password) {
> // login code goes here
> Map model = new HashMap();
> model.put("message", "Login successful");
> return new ModelAndView("default", "model", model);
> }
>
> And fragment of the configuration code:
>
> <!--
> - This bean is an explicit URL mapper that is used by the dispatcher
> - servlet.
> - It is used instead of the default BeanNameUrlHandlerMapping.
> -->
> <bean id="urlMapping"
> class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
> <property name="mappings">
> <props>
> <prop key="/**/*.htm">controller</prop>
> </props>
> </property>
> </bean>
>
> <!--
> - A POJO whose methods will handle web requests.
> -->
> <bean id="simple" class="web.extensions.simple.Simple">
>
> </bean>
>
> <!--
> - A Controller dispatching web requests to a POJO.
> -->
> <bean id="controller" class="web.extensions.ActionSetController">
> <property name="actionSet">
> <ref local="simple"/>
> </property>
> </bean>
>
> From my experience complex web applications always have large number of
> methods processing web requests. The methods have to deal with web
> request parameters, but they don't have to handle user form submissions
> and don't require data validation. For example, a server script would
> generate an URL which clicked by user would change web application state
> somehow. Building separate Command objects for every controller method
> would be overkill, dealing with servlet's parameter maps is annoyance.
> This is where metadata comes to help. I believe the example code above
> is a small piece of what can be done with attributes, they can solve
> wider range of problems of web applications.
>
> I've written initial working demo, which is in alpha state now. As
> youmay guess it is Spring's AbstractController implementation. I used
> Apache commons-attributes, because of their compatibility with JDK1.4,
> but JDK1.5 annotations are also possible.
>
> I'd like to ask the community, what do you think about the idea? Do you
> lake it? Does it have any future? Is so, may be it isthe time to
> implement it in some framework? I would appreciate any feedback from you.
>
> Thanks, Alex.
>
> PS
> Happy New 2005 Year!!!
>
>
>
> package web.extensions.simple;
>
> import org.springframework.web.servlet.ModelAndView;
>
> import java.util.HashMap;
> import java.util.Map;
>
> /**
> * Simple action handler, defines default view name for the action
> * methods that don't specify their own ones.
> *
> * @@web.extensions.ActionSet(defaultActionHandler="welcome",
> * defaultViewName="default")
> */
> public class Simple {
>
> /**
> * The simplest method ever, it does not take any parameters nor
> * does it return anything. Returned view name is taken from class
> * annotation.
> *
> * @@web.extensions.ActionHandler("/welcome")
> */
> public void welcome() {
> // custom code goes here
> }
>
> /**
> * Simple method, implicitly specifies returned view name in its
> * annotation.
> *
> * @@web.extensions.ActionHandler("/simple/simple1",
> * defaultViewName="view1")
> */
> public void simple1() {
> // custom code goes here
> }
>
> /**
> * Simple method, exclicitly scpecifies returned view name in the
> * returning string.
> *
> * @@web.extensions.ActionHandler("/simple/simple2")
> */
> public String simple2() {
> // custom code goes here
> return "view2";
> }
>
> /**
> * A more complicated method, which returns <em>ModelAndView</em>.
> *
> * @@web.extensions.ActionHandler("/simple/simple3")
> */
> public ModelAndView simple3() {
> // custom code goes here
> Map model = new HashMap();
> model.put("message", "Hello World (executing simple3)");
> return new ModelAndView("view3", "model", model);
> }
>
> /**
> * This action would be invoked when <em>"/simple/action"</em>
> * path is requested and no <em>switch</em> parameter is specified
> * in the request's values.
> *
> * @@web.extensions.ActionHandler("/simple/action")
> * @see #actionSwitchAbc()
> * @see #actionSwitchXyz()
> */
> public ModelAndView actionDefault() throws Exception {
> Map model = new HashMap();
> model.put("message",
> "invoking <em>action</em>, the switch parameter is not specified");
> return new ModelAndView("default", "model", model);
> }
>
> /**
> * An example of a method which would only be invoked if a certain
> * request's parameter has the specified value. This action would
> * be invoked when <em>"/simple/action"</em> path is requested and
> * the <em>switch</em> parameter is <em>abc</em>.
> *
> * @@web.extensions.ActionHandler("/simple/action?switch=abc")
> * @see #actionDefault()
> * @see #actionSwitchXyz()
> */
> public ModelAndView actionSwitchAbc() throws Exception {
> Map model = new HashMap();
> model.put("message",
> "invoking <em>action</em>, the switch parameter is 'abc'");
> return new ModelAndView("default", "model", model);
> }
>
> /**
> * An example of a method which would only be invoked if a certain
> * request's parameter has the specified value. This action would
> * be invoked when <em>"/simple/action"</em> path is requested and
> * the <em>switch</em> parameter is <em>xyz</em>.
> *
> * @@web.extensions.ActionHandler("/simple/action?switch=xyz")
> * @see #actionDefault()
> * @see #actionSwitchAbc()
> */
> public ModelAndView actionSwitchXyz() throws Exception {
> Map model = new HashMap();
> model.put("message",
> "invoking <em>action</em>, the switch parameter is 'xyz'");
> return new ModelAndView("default", "model", model);
> }
>
> /**
> * A more advanced example. Method's arguments are taken from the
> * corresponding request's values. Here the <em>userId</em>
> * argument is taken from the <em>uid</em> request's parameter
> * converted to integer. If none is specified then default one is
> * choosen. The <em>username</em> and <em>password</em> arguments
> * are mandatory.
> *
> * @@web.extensions.ActionHandler("/simple/dummylogin")
> * @@.userId web.extensions.ActionParam("uid", defaultValue=0)
> * @@.email web.extensions.ActionParam("eml", required=true)
> * @@.password web.extensions.ActionParam("pwd", required=true)
> */
> public ModelAndView dummylogin(int userId, String email, String password) {
> // login code goes here
> Map model = new HashMap();
> model.put("message", "Login successful");
> return new ModelAndView("default", "model", model);
> }
>
> /**
> * A counterpart of the {@link Simple#dummylogin(int, String,
> * String) dummylogin} method.
> *
> * @@web.extensions.ActionHandler("/simple/dummylogout")
> */
> public void dummylogout() {
> // perform logout and redirect to the login view.
> }
>
> }
>
>
>
|
|
From: Aliaksandr R. <ara...@gm...> - 2004-12-30 17:50:35
|
But hey, where is my original message? I don't see it in this list. I posted the message via 'news.gmane.org' newsgroup. Steven Devijver wrote: > Hi Aliaksandr, > > Looks nice. Does this framework have a name or shall I just refer to > it as YAWF? :-) > > Can we download a distribution somewhere? > > Steven > |
|
From: Aliaksandr R. <ara...@gm...> - 2004-12-30 17:55:41
|
Here it is: http://caustic.at.tut.by/yawf-0.0.1.zip I'm not sure about name, I believe that name is the most important thing for any framework. It doesn’t really matter whether a framework is poor if its name sounds good ;) I haven’t chosen any good name yet, but mostly because the framwork doesn't exist yet ;) Steven Devijver wrote: > Hi Aliaksandr, > > Looks nice. Does this framework have a name or shall I just refer to > it as YAWF? :-) > > Can we download a distribution somewhere? > > Steven > > > > On Thu, 30 Dec 2004 16:11:00 +0200, Aliaksandr Radzivanovich > <ara...@gm...> wrote: > >>Hello everybody, you got it right - Yet Another Web Framework ;) >>Everybody loves writing web frameworks, so I do ;))) >>My idea is to annotate POJOs, their methods and arguments with metadata >>to make them web request handlers. I've never heart of this approach >>before, correct me if I'm wrong. Let me explain it in details, let's >>start from example. Take a look at the following snippets of code, pay >>your attention to the javadocs: >> >>Here is declaration of a POJO whose methods will handle web requests: >> >>/** >> * Simple action handler, defines default view name for the action >> * methods that don't specify their own ones. >> * >> * @@web.extensions.ActionSet(defaultViewName="default") >> */ >>public class Simple { >> ... >> >>Here is the method which would handle requests to "/welcome.htm": >> >>/** >> * The simplest method ever, it does not take any parameters nor >> * does it return anything. Returned view name is taken from class >> * annotation. >> * >> * @@web.extensions.ActionHandler("/welcome") >> */ >>public void welcome() { >> // custom code goes here >>} >> >>Here is the method whose arguments are taken from request values. >> >>/** >> * A more advanced example. Method's arguments are taken from the >> * corresponding request's values. Here the <em>userId</em> >> * argument is taken from the <em>uid</em> request's parameter >> * converted to integer. If none is specified then default value is >> * choosen. The <em>username</em> and <em>password</em> arguments >> * are mandatory. >> * >> * @@web.extensions.ActionHandler("/simple/dummylogin") >> * @@.userId web.extensions.ActionParam("uid", defaultValue=0) >> * @@.email web.extensions.ActionParam("eml", required=true) >> * @@.password web.extensions.ActionParam("pwd", required=true) >> */ >>public ModelAndView dummylogin(int userId, String email, String password) { >> // login code goes here >> Map model = new HashMap(); >> model.put("message", "Login successful"); >> return new ModelAndView("default", "model", model); >>} >> >>And fragment of the configuration code: >> >><!-- >> - This bean is an explicit URL mapper that is used by the dispatcher >> - servlet. >> - It is used instead of the default BeanNameUrlHandlerMapping. >> --> >><bean id="urlMapping" >>class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> >> <property name="mappings"> >> <props> >> <prop key="/**/*.htm">controller</prop> >> </props> >> </property> >></bean> >> >><!-- >> - A POJO whose methods will handle web requests. >> --> >><bean id="simple" class="web.extensions.simple.Simple"> >> >></bean> >> >><!-- >> - A Controller dispatching web requests to a POJO. >> --> >><bean id="controller" class="web.extensions.ActionSetController"> >> <property name="actionSet"> >> <ref local="simple"/> >> </property> >></bean> >> >> From my experience complex web applications always have large number of >>methods processing web requests. The methods have to deal with web >>request parameters, but they don't have to handle user form submissions >>and don't require data validation. For example, a server script would >>generate an URL which clicked by user would change web application state >>somehow. Building separate Command objects for every controller method >>would be overkill, dealing with servlet's parameter maps is annoyance. >>This is where metadata comes to help. I believe the example code above >>is a small piece of what can be done with attributes, they can solve >>wider range of problems of web applications. >> >>I've written initial working demo, which is in alpha state now. As >>youmay guess it is Spring's AbstractController implementation. I used >>Apache commons-attributes, because of their compatibility with JDK1.4, >>but JDK1.5 annotations are also possible. >> >>I'd like to ask the community, what do you think about the idea? Do you >>lake it? Does it have any future? Is so, may be it isthe time to >>implement it in some framework? I would appreciate any feedback from you. >> >>Thanks, Alex. >> >>PS >>Happy New 2005 Year!!! >> >> >> >>package web.extensions.simple; >> >>import org.springframework.web.servlet.ModelAndView; >> >>import java.util.HashMap; >>import java.util.Map; >> >>/** >> * Simple action handler, defines default view name for the action >> * methods that don't specify their own ones. >> * >> * @@web.extensions.ActionSet(defaultActionHandler="welcome", >> * defaultViewName="default") >> */ >>public class Simple { >> >> /** >> * The simplest method ever, it does not take any parameters nor >> * does it return anything. Returned view name is taken from class >> * annotation. >> * >> * @@web.extensions.ActionHandler("/welcome") >> */ >> public void welcome() { >> // custom code goes here >> } >> >> /** >> * Simple method, implicitly specifies returned view name in its >> * annotation. >> * >> * @@web.extensions.ActionHandler("/simple/simple1", >> * defaultViewName="view1") >> */ >> public void simple1() { >> // custom code goes here >> } >> >> /** >> * Simple method, exclicitly scpecifies returned view name in the >> * returning string. >> * >> * @@web.extensions.ActionHandler("/simple/simple2") >> */ >> public String simple2() { >> // custom code goes here >> return "view2"; >> } >> >> /** >> * A more complicated method, which returns <em>ModelAndView</em>. >> * >> * @@web.extensions.ActionHandler("/simple/simple3") >> */ >> public ModelAndView simple3() { >> // custom code goes here >> Map model = new HashMap(); >> model.put("message", "Hello World (executing simple3)"); >> return new ModelAndView("view3", "model", model); >> } >> >> /** >> * This action would be invoked when <em>"/simple/action"</em> >> * path is requested and no <em>switch</em> parameter is specified >> * in the request's values. >> * >> * @@web.extensions.ActionHandler("/simple/action") >> * @see #actionSwitchAbc() >> * @see #actionSwitchXyz() >> */ >> public ModelAndView actionDefault() throws Exception { >> Map model = new HashMap(); >> model.put("message", >> "invoking <em>action</em>, the switch parameter is not specified"); >> return new ModelAndView("default", "model", model); >> } >> >> /** >> * An example of a method which would only be invoked if a certain >> * request's parameter has the specified value. This action would >> * be invoked when <em>"/simple/action"</em> path is requested and >> * the <em>switch</em> parameter is <em>abc</em>. >> * >> * @@web.extensions.ActionHandler("/simple/action?switch=abc") >> * @see #actionDefault() >> * @see #actionSwitchXyz() >> */ >> public ModelAndView actionSwitchAbc() throws Exception { >> Map model = new HashMap(); >> model.put("message", >> "invoking <em>action</em>, the switch parameter is 'abc'"); >> return new ModelAndView("default", "model", model); >> } >> >> /** >> * An example of a method which would only be invoked if a certain >> * request's parameter has the specified value. This action would >> * be invoked when <em>"/simple/action"</em> path is requested and >> * the <em>switch</em> parameter is <em>xyz</em>. >> * >> * @@web.extensions.ActionHandler("/simple/action?switch=xyz") >> * @see #actionDefault() >> * @see #actionSwitchAbc() >> */ >> public ModelAndView actionSwitchXyz() throws Exception { >> Map model = new HashMap(); >> model.put("message", >> "invoking <em>action</em>, the switch parameter is 'xyz'"); >> return new ModelAndView("default", "model", model); >> } >> >> /** >> * A more advanced example. Method's arguments are taken from the >> * corresponding request's values. Here the <em>userId</em> >> * argument is taken from the <em>uid</em> request's parameter >> * converted to integer. If none is specified then default one is >> * choosen. The <em>username</em> and <em>password</em> arguments >> * are mandatory. >> * >> * @@web.extensions.ActionHandler("/simple/dummylogin") >> * @@.userId web.extensions.ActionParam("uid", defaultValue=0) >> * @@.email web.extensions.ActionParam("eml", required=true) >> * @@.password web.extensions.ActionParam("pwd", required=true) >> */ >> public ModelAndView dummylogin(int userId, String email, String password) { >> // login code goes here >> Map model = new HashMap(); >> model.put("message", "Login successful"); >> return new ModelAndView("default", "model", model); >> } >> >> /** >> * A counterpart of the {@link Simple#dummylogin(int, String, >> * String) dummylogin} method. >> * >> * @@web.extensions.ActionHandler("/simple/dummylogout") >> */ >> public void dummylogout() { >> // perform logout and redirect to the login view. >> } >> >>} >> >> >> |