| <?xml version="1.0"?> |
| <!-- |
| /* |
| * Copyright 2001-2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| --> |
| |
| <document> |
| |
| <properties> |
| <title>Turbine Services - RunData Service</title> |
| </properties> |
| |
| <body> |
| |
| <section name="RunData Service"> |
| |
| <p> |
| RunData is an interface that is passed around within Turbine. RunData |
| provides the threading mechanism, as there is one RunData object per |
| HTTP request. The RunData service manages the isues surrounding multiple |
| requests being accepted. TurbineRunData is the interface that is |
| specific to the Turbine RunData service, and via the recyclable |
| interface can be sent back to the Factory for recycling. |
| </p> |
| |
| <p> |
| RunData objects should never be held on to across requests. They are |
| considered one time only objects. |
| </p> |
| |
| <p> |
| All this higher level processing by the service means that for each HTTP |
| request there is an interface that is castable to, or available, that |
| can be used to access all information to do with that request. As an |
| example, information such as the content type of the request and the |
| response can be queried or sent, as well as other information |
| surrounding servlet HTTP management, such as Sessions, PrintWriters as |
| well as Turbine specific information such as Users, AccessControlLists, |
| Templating, Error Handling and Contexts. |
| </p> |
| |
| </section> |
| |
| <section name="Configuration"> |
| |
| <p> |
| In the TurbineResources.properties the service needs to be defined for |
| Turbine to initialize with. |
| </p> |
| |
| |
| <source><![CDATA[ |
| # ------------------------------------------------------------------- |
| # |
| # S E R V I C E S |
| # |
| # ------------------------------------------------------------------- |
| # Classes for Turbine Services should be defined here. |
| # Format: services.[name].classname=[implementing class] |
| # |
| # To specify properties of a service use the following syntax: |
| # service.[name].[property]=[value] |
| |
| services.TurbineRunDataService.classname=org.apache.turbine.services.rundata.TurbineRunDataService |
| . |
| . |
| . |
| # ------------------------------------------------------------------- |
| # |
| # R U N D A T A S E R V I C E |
| # |
| # ------------------------------------------------------------------- |
| # Default implementations of base interfaces for request processing. |
| # Additional configurations can be defined by using other keys |
| # in the place of the <default> key. |
| # ------------------------------------------------------------------- |
| |
| services.RunDataService.default.run.data=org.apache.turbine.services.rundata.DefaultTurbineRunData |
| services.RunDataService.default.parameter.parser=org.apache.turbine.util.parser.DefaultParameterParser |
| services.RunDataService.default.cookie.parser=org.apache.turbine.util.parser.DefaultCookieParser |
| ]]></source> |
| |
| </section> |
| |
| <section name="Using RunData"> |
| |
| <p> |
| As RunData encapsulates all aspects of Turbine's gathering the |
| HttpRequest and sending the HttpResponse, any status to do with the |
| Request can be queried and any manipulation of the final response can be |
| carried out through the RunData Object. |
| </p> |
| |
| <p> |
| Turbine is a servlet and the functionality equated with the |
| javax.servlet and javax.servlet.http can be manipulated through the |
| RunData interface. One of the most useful components of the Servlet |
| libraries was Sessions. These are accessed through RunData; it also |
| provides direct access to the PrintWriter, Server details, Content |
| Types, ContextPath, Redirections, Client details, etc. Some of the |
| functions which equate with the servlet libraries are: |
| </p> |
| |
| <source><![CDATA[ |
| getLocale() |
| setLocale(Locale locale) |
| getCharSet() |
| setCharSet(String charset) |
| getContentType() |
| setContentType(String mimetype) |
| getOut() //get PrintWriter Object |
| getRedirectURI() |
| getRemoteAddr() |
| getRemoteHost() |
| getRequest() |
| getResponse() |
| getServletContext() |
| getSession() |
| getStatusCode() |
| ]]></source> |
| |
| <p> |
| The get/setLocale(), get/setCharSet() and get/setContentType() methods |
| are used for specifying the locale, character encoding and content type |
| of the body of the servlet response. |
| </p> |
| |
| <p> |
| The method setLocale() is called to specify explicitly the locale |
| of the response. If setLocale() is not called, the "locale.default.language" |
| and "locale.default.country" properties from Turbine Resources are used to |
| determine the locale. If these properties are not set, the JVM's default |
| locale determines the locale. |
| </p> |
| |
| <p> |
| If the locale is set to something else than the default locale or Locale.US, |
| an explicit encoding is not specified with the setCharSet() method or the |
| "locale.default.charset" property, and the main MIME type of the content is |
| "text", the getContentType() method adds a locale specific encoding (charset) |
| to the content type automatically. |
| </p> |
| |
| <p> |
| The locale specific charset is obtained from the MimeTypeService, which |
| maintains mappings between locales and charsets. |
| </p> |
| |
| <p> |
| As always consult the Javadocs for more detail. |
| </p> |
| |
| <p> |
| To use Turbine to only manipulate the functions that came with the Sun |
| Servlet libraries is to miss out on Turbine's power. Turbine is a |
| framework which enables manipulation of the HttpResponse and HttpRequest |
| above and beyond the simple Servlet libraries. Turbine has services and |
| layers surrounding those available with the Response and Request that |
| allow easier creation and management of Websites and Web-enabled |
| Applications. In fact you wont have to type import javax.servlet.* |
| again! |
| </p> |
| |
| </section> |
| |
| <section name="Session Management"> |
| <p> |
| Sessions are managed in Turbine via the User interface. The User |
| interface allows for a blend of cookie management, memory management and |
| relational database to be used to manage a user's session. A user of the |
| site can have their Turbine session set as either temporary storage or |
| permanent storage. The permanent storage will survive a servlet engine |
| restart. How all this is managed by Turbine is transparent to the Java |
| Engineer. As an example assume we want to monitor how often a user |
| returns to the website we are developing and we want to reward them for |
| their returning interaction: |
| </p> |
| |
| <source><![CDATA[ |
| //in Login Action class |
| public void doPerform(RunData data, Context context) |
| throws Exception |
| { |
| //get the Parameters, username and password |
| ParameterParser params = data.getParameters(); |
| String loginname = params.getString("username"); |
| String password = params.getString("password"); |
| |
| try |
| { |
| //cast to TurbineUser interface |
| //and check if user is in system |
| TurbineUser user = (TurbineUser) |
| TurbineSecurity |
| .getAuthenticatedUser(loginname, password); |
| |
| //put User into Session |
| data.setUser(user); |
| |
| //mark the User as logged in |
| user.setHasLoggedIn(new Boolean(true)); |
| |
| //add to the access counter |
| user.incrementAccessCounter(); |
| |
| //add to the access counter for the session |
| user.incrementAccessCounterForSession(); |
| |
| //check to see if user is to have |
| //their status changed to valued |
| if(user.getAccessCounter() > 500 ) |
| { |
| //set into persistant storage |
| //that our visitor is now a |
| //valued user |
| user.setPerm("valued", new Boolean(true)); |
| } |
| |
| data.save(); |
| } |
| catch (Exception e) |
| { |
| //error handling |
| } |
| } |
| ]]></source> |
| |
| <p> |
| While skeletal this shows a good example of permanent and temporary |
| management of User information. The line data.setUser() puts the User |
| into session, the hasLoggedIn() method updates the User Object to |
| reflect the fact that the session has passed Authentication; however |
| until the RunData's save method is called both the User and hasLoggedIn |
| flag are only existing in Turbine's memory. Neither become a part of |
| RunData's HttpSession until they are saved into the session through |
| data.save(). The AccessCounter is persistent storage and is saved into |
| the database. The AccessCounter for the session counts the number of |
| pages that are requested throgh Turbine for the user's session. Once |
| their session logs out or the session times out, that information is |
| lost. The user.setPerm() method allows for information to be stored |
| persistently into the database as a HashTable entry. The example above |
| was intended to show that information can be handled through a |
| consistent interface allowing for the management at the |
| request/response, session and persistent levels without any direct |
| manipulation of the HttpRequest, HttpResponse, HttpSession or Relational |
| database. As always, refer to the Javadocs for more information on the |
| RunData, User and TurbineUser interfaces. |
| </p> |
| |
| </section> |
| |
| <section name="Parameter and Cookie Parsing"> |
| <p> |
| One of the most useful parts of the RunData interface is the easy |
| retrieval of parameters attached to a request. The ParameterParser and |
| CookieParser Interfaces are available through the RunData interface and |
| provide convenience methods for gathering parameters from either the URI |
| or Session. Turbine handles parameters as name/value pairs through the |
| URI via the BaseValueParser object, allowing the parameters to be |
| requested as a Java type rather than a catch-all: |
| </p> |
| |
| <source><![CDATA[ |
| /** the doPerform method from Invoice.java Action class */ |
| public void doPerform(RunData data, Context context) throws Exception |
| { |
| //get parameters |
| ParameterParser params = data.getParameters(); |
| |
| /** |
| * Where "units" is the HTML Input Form name |
| */ |
| int units = params.getInt("units"); |
| |
| /** |
| * Get the description, if there is no entry from the |
| * HTML input form, set the default as "No Description". |
| */ |
| String description = params.getString("description","No Description"); |
| |
| /** |
| * If there is no total, set the value to 0. |
| */ |
| BigDecimal total = params.getBigDecimal("total",new BigDecimal(0)); |
| } |
| ]]></source> |
| |
| <p> |
| The above example shows gathering of name/value pairs from HTML Form |
| Inputs and setting default values for those forms. In the case of |
| description, if the description is null, then the default value "No |
| Description" will be substituted. The Javadocs for ParameterParser show |
| more information on the methods available. |
| </p> |
| |
| </section> |
| |
| <section name="Security Management"> |
| |
| <p> |
| The RunData interface also exposes security management methods and |
| information which are encapsulated into a request. The RunData interface |
| exposes the AccessControlList Object, which encapsulates the Permissions |
| and Roles for the Groups the User is in. The getACL() method allows for |
| the permission of the User to be queried against their ACL. |
| </p> |
| |
| <source><![CDATA[ |
| /** the doPerform method from DeleteInvoice.java Action class */ |
| public void doPerform(RunData data, Context context) throws Exception |
| { |
| //check if the User is authorized before |
| //deleting the invoice |
| AccessControlList acl = data.getACL(); |
| if(acl.hasPermission("deleteinvoice")) |
| { |
| //delete invoice logic |
| } |
| else |
| { |
| data.setMessage("You do not have permission to delete an invoice."); |
| data.setTemplate(data, "UnauthorizedRequest.vm"); |
| } |
| } |
| ]]></source> |
| |
| <p> |
| The above example gets the AccessControlList Object for the User through |
| the RunData interface. The ACL is used to check against the Permissions |
| the User has, the PermissionSet, or a list of all permissions the User |
| has, most likely taken from a database. In this example, the check is |
| against the string "deleteinvoice". If the User has the permission, they |
| will be able to delete the invoice, otherwise the User will get an |
| unauthorized request Velocity screen. |
| </p> |
| |
| </section> |
| |
| <section name="Template Management"> |
| |
| <p> |
| The RunData also exposes methods to manipulate Screens, Actions, Pages |
| and Layouts. The templating service assembles the screens, actions and |
| layouts as well as exposing template methods. The methods for managing |
| screens and actions includes: |
| </p> |
| |
| <source><![CDATA[ |
| getAction() |
| getLayout() |
| getLayoutTemplate() |
| getScreen() |
| getTemplateInfo() //returns TemplateInfo Object |
| hasAction() |
| hasScreen() |
| setAction() |
| setLayout() |
| setLayoutTemplate() |
| setScreen() |
| setScreenTemplate() |
| ]]></source> |
| |
| <p> |
| For more information on how to use the RunData Interface with Velocity |
| templates and the Velocity context, view the Velocity Site |
| documentation. |
| </p> |
| |
| </section> |
| |
| <section name="Messaging"> |
| |
| <p> |
| One of the other useful wrappers the RunData interface provides access |
| to is messaging. The Message can be set as a String, an ECS Element or |
| as a FormMessages object. RunData contains access to other convenience |
| methods to do with Messaging such as: |
| </p> |
| |
| <source><![CDATA[ |
| addMessage(Element msg) |
| addMessage(String msg) |
| hasMessage() //if the request has a message |
| getMessage() |
| getMessageAsHTML() |
| getMessages() //returns a FormMessages Object |
| setMessage(String msg) |
| setMessage(Element msg) |
| setMessage(FormMessages msgs) |
| ]]></source> |
| |
| <p> |
| An example of using messages with Velocity templates in an action is |
| below: |
| </p> |
| |
| <source><![CDATA[ |
| /** the doPerform method from Invoice.java Action class */ |
| public void doPerform(RunData data, Context context) throws Exception |
| { |
| data.setMessage("A message for output."); |
| data.setTemplate(data, "Test.vm"); |
| } |
| ]]></source> |
| |
| <p> |
| This would be accessed in the Velocity template via: |
| </p> |
| |
| <source><![CDATA[ |
| #* |
| Velocity file, Test.vm, showing messaging example. |
| *# |
| |
| $data.getMessage() |
| ]]></source> |
| |
| <p> |
| And the output would be: |
| </p> |
| |
| <source><![CDATA[ |
| A message for output. |
| ]]></source> |
| |
| <p> |
| The Javadocs for RunData show all the methods available through the |
| interface and is definitely the place to start when looking for more |
| information on what RunData exposes. The RunData interface is one of the |
| most important areas for a Java Engineer to understand and be familiar |
| within the Turbine Framework. Understanding RunData is of continual |
| benefit. |
| </p> |
| |
| </section> |
| |
| </body> |
| </document> |