|
Orion Filter Tutorial, Lesson 3, Manipulating the Response In this part of the Orion filter tutorial, we will build a simple Filter that will be used to manipulate the response to a request. 1 Introduction In this part of the Orion filter tutorial, we will build a simple Filter that will be used to manipulate the response to a request. In order to do this we will need an HttpServletResponseWrapper, a custom ServletOutputStream and a Filter. In order to test the Filter, we will also need a JSP page to attach our filter to. We will then configure the usage of this filter, and finally test it. The Filter will use an HttpSerlvetResponseWrapper to wrap the Response before it is sent to the target of the request.
An HttpSerlvetResponseWrapper is an object that acts as a Wrapper or Decorator to the ServletResponse object. It is used to wrap the real Response so that we can modify it after that the target of the request has delivered its response. The HttpServletResponseWrapper that we are going to develop will use a custom ServletOutputStream that lets us manipulate the data after that the target of the request is done with it. Normally, this cannot be done after that the ServletOutputStream has been closed.
2 Creating the FilterServletOutputStream Normally, the ServletOutputStream cannot be modified after a resource has committed it. We will therefore need to implement our own extension to the ServletOutputStream. Later on, you will see how we will use this FilterServletOutputStream to manipulate the response of another resource.
We will create the FilterServletOutputStream in the following steps: 2.1 Step 1: Create a file named 'FilterServletOutputStream.java' Fire up your editor and start editing a source file with the name 'FilterServletOutputStream.java' 2.2 Step 2: Add import statements Start of with the package name and any imports we need, so that your source looks like the following:
This will make sure that we have the neccessary classes available. 2.3 Step 3: Add class declaration Continue with the following:
Above we let the FilterServletOutputStream extend the normal ServletOutputStream and make sure that we keep hold of a DataOutputStream. 2.4 Step 4: Add constructor Add a simple constructor to this class as described below:
Our constructor makes sure that whenever a FilterServletOutputStream is created, we will cast the given OutputStream into a DataOutputStream. 2.5 Step 5: Implement necessary methods Now lets finish this class by implementing all the various methods we need to be a valid ServletOutputStream:
Your FilterServletOutputStream.java should now look like this. 2.6 Step 6: compile your FilterServletOutputStream Compile your FilterServletOutputStream. Your FilterServletOutputStream.class should be located in the 'orion/default-web-app/WEB-INF/classes/com/acme/filter/' directory when done. 3 Creating the GenericResponseWrapper In order to use our custom ServletOutputStream we will need to implement a class that can act as a Response object. We will send this Wrapper to the target of the request instead of the original Response object.
We will create the GenericResponseWrapper in the following steps:
Step 2: Add import statements Step 3: Add class declaration Step 4: Add constructor Step 5: Handle binary content Step 6: Retrieving the content Step 7: Handle character content Step 8: Handling content-length Step 9: Retrieving the content-length Step 12: compile your Wrapper 3.1 Step 1: Create a file named 'GenericResponseWrapper.java' Start up your editor and start editing a source file with the name 'GenericResponseWrapper.java' 3.2 Step 2: Add import statements Start of with the package name and any imports we need, so that your source looks like the following:
This will make sure that we have the neccessary classes available. 3.3 Step 3: Add class declaration Continue with the following:
Above we let the GenericResponseWrapper extend the HttpServletResponseWrapper. We also declare three instance variables; a ByteArrayOutputStream that will hold any content written by the target of the request, a int to hold the content length and a String to hold the contentType. 3.4 Step 4: Add constructor Continue with adding the following constructor:
The constructor makes sure that the response is passed to the constructor of the HttpServletResponse. Finally, we set the output to hold a new ByteArrayOutputStream. 3.5 Step 5: Handle binary content Continue with adding the following method:
The method above will be used by the target of the request when writing its binary response. 3.6 Step 6: Retrieving the content Continue with adding the following method:
Above we add a convenient method for obtaining the data written to the ByteArrayOutputStream. 3.7 Step 7: Handle character content Continue with the following method:
The method above will be used by the target of the request when writing its character text response. 3.8 Step 8: Handling content-length Now, anyone who told you that size does not matter is lying. If we are going to manipulate the response we need to reset its content-length. Continue with the following method:
The methods above will be used to set and get the content length or the response. We override these method and make sure that we can obtain this value at a later time. 3.9 Step 9: Retrieving the content-length Continue with the following method:
The methods above can be used to set and retrieve the content length of the response. Your GenericResponseWrapper.java should now look like this. When developing your own custom Filters, you probably want to implement more functionality into your wrappers. Please feel free to use this sample as a base for such extenssions. 3.10 Step 12: compile your Wrapper Compile your Wrapper. Your GenericResponseWrapper.class should be located in the 'orion/default-web-app/WEB-INF/classes/com/acme/filter/' directory when done. 4 Writing the Filter Now its time to write the Filter that will use our generic Response wrapper. This filter will just add content to the response of the target of the request before and after that the target is invoked. This Filter will extend the GenericFilter that we developed in lesson 1. Grab the GenericFilter from lesson 1 here.
We will create the PrePostFilter in the following steps: 4.1 Step 1: Create a file named 'PrePostFilter.java' Fire up your editor and start editing a source file with the name 'PrePostFilter.java' 4.2 Step 2: Add import statements Start of with the package name and any imports we need, so that your source looks like the following:
This will make sure that we have the neccessary classes available. 4.3 Step 3: Add class declaration Continue with the following:
Above we let the PrePostFilter extend the GenericFilter. 4.4 Step 4: Override the doFilter() method We shall now override the doFilter() method inherited from the GenericFilter class with the following method:
In the code above, we first print a message to our own ServletOutputStream. After that, we use our Response to create a new GenericResponseWrapper. Continue the method with the following lines of code:
In the code above, we pass on our newly created GenericResponseWrapper to the next Filter in the chain. As said before, if there are now more filters in the chain, this will invoke the initial target of the request. We then write the response received to our ServletOutputStream by using our wrappers getData() method, which contains the response of the Filter called previously. After that, we print out a message to our ServletOutputStream. Your PrePostFilter.java should now look like this. 4.5 Step 5: compile your PrePostFilter Compile your PrePostFilter. Your PrePostFilter.class should be located in the 'orion/default-web-app/WEB-INF/classes/com/acme/filter/' directory when done. 5 Creating a JSP page to test the Filter Now, in order to use our filter we need to attach that filter to something. We will create a real simple JSP page and place it in the root of the default-web-app. We will create the JSP page in the following steps: 5.1 step 1: Create a file named 'filter3.jsp' Fire up your editor so that you can create a file called 'filter3.jsp'. 5.2 step 2: Write the source Add the following to your file:
The JSP page above will write out a dummy message when invoked. 5.3 step 3: Save the JSP page Save your file in the 'orion/default-web-app/' directory with the name 'filter3.jsp'. Your JSP page should now look like this. 6 Configuring your Filter It is now time for us to configure our Filter usage. To do so we will go through the following steps: 6.1 Step 1: Configure Filter existence in web.xml Start up your editor and open the file 'orion/default-web-app/WEB-INF/web.xml'. After the configuration of the 'message' Filter, add the following rows:
This will tell the container that our web-application has yet another filter that we will refer to as 'prePost', which represents the class 'com.acme.filter.PrePostFilter'. 6.2 Step 2: Configure Filter mapping in web.xml After the mapping configuration of the 'message' Filter, add the following rows:
This will tell our container that within this web-application, any requests for '/filter3.jsp' will first invoke the filter named 'prePost'. 6.3 Step 3: Save changes to web.xml Save your 'web.xml' and make sure that it is located in the 'orion/default-web-app/WEB-INF/' directory. Your web.xml should now look something like this. 7 Testing your Filter It is now time to test our Filter. We will do so in the following steps: 7.1 Step 1: Make sure Orion is running Make sure that your Orion Application Server is up and running. 7.2 Step 2: Open the URL Open up the location 'http://localhost/filter3.jsp' in a normal browser. Substitute 'localhost' with the name of the server you are working with if needed. The result should be the content of the filter3.jsp file inside a PRE and POST printout. Congratulations! You have just created and successfully tested your first response-altering filter! Continue with Lesson 4, Manipulating a MultiMedia Response. Copyright © 2003 IronFlare AB |