views:

347

answers:

4

I'm writing a very simple web framework using Java servlets for learning purposes. I've done this before in PHP, and it worked by consulting the request URI, then instantiating the appropriate class and method.

This worked fine in PHP, as one can do something like $c = new $x; $x->$y;. I'm unsure however of how to translate this to Java, or even if this is an appropriate way to go about it.

So far, I've tried:

Router router = new Router(request.getPathInfo());
String className = router.route(); //returns com.example.controller.Foo

Class c = Class.forName(className);
Object x = c.newInstance();

Foo y = (Foo) x;
y.doSomething();

This seems fine for a couple of routes, but doesn't seem like it would scale well, nor would it allow for sourcing routes from a configuration file.

How should I make it work?

A: 

Not quite sure what you're after but you might want to take a look at Java servlets. Granted many web frameworks are abstracted above plain servlets, but it's a jolly good place to start learning about Java web apps if you ask me (which indirectly you did ;) )

Download the Java servlet specification here: Java Servlet Spec - it's quite interesting.

Tom Duckering
Oops, I forgot to mention that my code so far is implemented as a servlet.
etheros
... the Servlet spec is worth reading though.
deamon
A: 

How should you make it work? However you want it to. If you're just doing it for learning purposes, whatever you do will be fine.

I would suggest having all your actions implement the same interface though (maybe extend Servlet) so that you don't have to compile in all different classes.

Then you can essentially do what you're doing, except that your cast to Foo becomes a cast to Servlet and then you don't have to have a special case for all your different classes.

You can then also load up the routes from configuration (maybe an XML file).

Essentially what you're doing is implemented by the Struts 1 framework so it might be worthwhile reading up on that (it's open-source so you can also look at the source if you want).

Phill Sacre
+1  A: 

I would use a Servlet Filter as Front Controller. The router would connect paths with request dispatchers. In the doFilter method you would convert ServletRequest to HttpServletRequest, extract the request path and match it against the registered mappings. The result of this mapping is a request dispatcher you would dispatch the request with.

In pseudo code:

doFilter(ServletRequest request, ServletResponse response) {
  httpServletRequest = (HttpServletRequest) request;
  path = httpServletRequest.getRequestURI();
  dispatcher = router.getTarget(path);
  dispatcher.dispatch(request, response);
}

Depending on your need the default routing mechanism of the Servlet API could be sufficient.

deamon
Pathinfo isn't available in filters.
BalusC
pathinfo is available after casting ServletRequest to HttpServletRequest.
deamon
I didn't mean that :) It will always return null in filters.
BalusC
Maybe I remember something wrong with casting here, but I've written a filter that dispatches requests based on the path.
deamon
For that normally request URI/URL is been used (and yes, from the downcasted HttpServletRequest).
BalusC
You're right, I used `getRequestURI()`. I have corrected my example.
deamon
A: 

Get hold of actions in a Map<String, Action> where the String key represents less or more a combination of request method and request pathinfo. I've posted similar answer before here: http://stackoverflow.com/questions/2060128/java-front-controller/2060842#2060842

You can fill such a map either statically (hardcoding all actions) or dynamically (convention over configuration, looking up classes in a certain package, or scanning the entire classpath for classes with a certain annotation or implementing a certain interface).

And just stick to Servlet. The Filter isn't there for. At highest use it to forward the request to the controller Servlet. In the Servlet, just implement HttpServlet#service().

BalusC
The benefit of a filter is, that you can use it together with servlets that are not mapped by the front controller. Wicket uses this approach.
deamon
That would be a MVC "patch" to existing servlet based apps, not a fullfledged MVC framework.
BalusC