VRaptor for JForum developers
JForum3 uses VRaptor
as Web framework, which is great and extremely simple to use. You can learn about it a little more in their One Minute Tutorial
. Go there, take a look, and see how simple it is. For convenience, here's a quick resume of how VRaptor works:
- Each of your actions should be inside a class annotated with @Component, and you may call that Actions, Logic or even Components. Here in JForum we use the suffix Actions, as we consider each possible operation an action.
- Everything that can be accessed from an URL should be a public method in the Component (remember, the @Component class), and may or may not return a value (more of this later), as well may receive any numer of arguments - even objetcs.
- By default, VRaptor lets you use void or String as return type of your methods, which are then used to resolve which JSP should be renderized. In JForum we ignore this, and all methods can be void.
- If you want to pass arguments to the method (which are sent via any URL or HTML form), register them using the @Parameter annotation. This is necessary because the Java compiler discards the argument name, keeping only its type, so the @Parameter annotation is used as a workaround.
- If you want to pass something to the JSP, you can simple provide a getter in the @Component. However, as components may get large, a lot of getter methods would be necessary, and so JForum provides a Property Bag to handle that (see example above).
- Last, but not least, the JSP files should be in a directory with the exact same name of our component, and the file name should be the method which was called. So, if we are executing the method list of a component named forums, there should be a file named list.jsp inside a directory called forums inside the directory /templates/default
Examples
So, let's take a look at a real
component of JForum3.
01 // Declare a component named "adminCategories".
02 // This is the name we'll use in the URL later
03 @Component("adminCategories")
04 public class CategoryAdminActions {
05 private CategoryRepository categoryRepository;
06 private CategoryService categoryService;
07
08 // A ViewPropertyBag is used to make objects available to JSP
09 private ViewPropertyBag propertyBag;
10
11 // ViewService provides general utilities methods for the Component
12 private ViewService viewService;
13
14 // Main component constructor. All objects are automatically
15 // injected by an IoC (Inversion of Control) container.
16 public CategoryAdminComponent(CategoryRepository categoryRepository,
17 CategoryService categoryService,
18 ViewPropertyBag propertyBag,
19 ViewService viewService) {
20 this.categoryRepository = categoryRepository;
21 this.categoryService = categoryService;
22 this.propertyBag = propertyBag;
23 this.viewService = viewService;
24 }
25
26 /**
27 * Displays the form to add a new category
28 */
29 public void add() {
30 // Hey, an empty method?
31 // Yes, and it is functional. When called,
32 // VRaptor will render the "add.jsp" file
33 }
34
35 // Here we're in fact saving a new category
36 // Note the @Parameter annotation, which informs VRaptor that
37 // a series of arguments starting with "category" will be passed
38 // This url can be executed as "addSave.page?category.name=category1&category.order=1"
39 public void addSave(@Parameter(key = "category") Category category) {
40 this.categoryService.add(category);
41
42 // Here we force a redirect to the "list" action in the same component
43 this.viewService.redirectToAction(Actions.LIST);
44 }
45
46 // Shows the page to edit an existing category
47 // Again, note the @Parameter annotation, telling VRaptor
48 // that an argument named "categoryId" will be sent via the URL
49 public void edit(@Parameter(key = "categoryId") int categoryId) {
50 // Ops, propertyBag? What's that?
51 // A Property Bag "holds" objects that are send to the JSP, so
52 // we don't need to make getters for everything. In the
53 // .jsp, we can then make a call to ${category.name} or any
54 // other property
55 this.propertyBag.put("category", this.categoryRepository.get(categoryId));
56
57 // We don't have an "edit.jsp" file, but we can use "add.jsp",
58 // which for this case works just fine, as it's the same form
59 this.viewService.renderView(Actions.ADD);
60 }
61
62 // This will render the file "list.jsp"
63 public void list() {
64 this.propertyBag.put("categories", this.categoryRepository.getAllCategories());
65 }
66
67 // [ ... ]
68 // More methods here
69 // [ ... ]
70
71 }
|
Take a good look at the comments made in the source code. Can you see that it's everything pretty easy?
ViewPropertyBag and ViewService
There are two interesting classes being used in the previous
action, which are
ViewPropertyBag and
ViewService. Those classes are from JForum - not VRaptor - and are indented to make development easier.
ViewPropertyBag holds objects that are going to be used in the JSP file, which means that
everything you want to access in the respective JSP, you should add the property bag. This is much more simple than making a getter for every property, if we were using VRaptor's default configuration.
The second one, ViewService, is just an helper class used to make redirects and conditional view rendering easier, so we don't need to rely on VRaptor's config files for that. There are methods to redirect to a specific action in the same component or even on another component, as well to render some specific JSP file.