Re: WOFileUpload and 5.4
Re: WOFileUpload and 5.4
- Subject: Re: WOFileUpload and 5.4
- From: William Hatch <email@hidden>
- Date: Thu, 30 Oct 2008 19:26:19 -0400
Thanks Jake, I'll try that. But, it's not working at all for me;
either under tomcat or as a typical woa. The component has a data and
filePath binding, inside a typical wo form; the enctype is properly
set, submit button bound to a component action. On submit (the upload)
the page refreshes, but it's as if the method is never called; log
statements don't show up; nothing. I can understand the .war issue,
due to the WOServletAdaptor, but then why wouldn't it work as a
normal .woa either? (sorry for the typing out loud;-)
Bill
On Oct 30, 2008, at 5:49 PM, Jake MacMullin wrote:
There is a bug in WO 5.4 with how HTTP headers are handled when
deployed in a servlet container. I reported this (5711936) and it
has been marked as resolved in 'the latest seed release of Xcode
3.1, Developer preview 2. So perhaps this is the bug you are running
in to. Here's how it manifested itself to me:
When WebObjects applications are deployed in servlet containers,
the WebObjects application does not receive requests or generate
responses directly. Instead, the WOServletAdaptor sits in between
the WebObjects application and the servlet container. All requests
and responses are sent to the servlet container, which then
dispatches them to the WOServletAdaptor, which dispatches them to
the underlying WebObjects application. Responses are handled in the
same way, but in the opposite direction. A bug exists in how the
WOServletAdaptor and the WOMessage and WORequest classes handle
HTTP headers. It seems that WOMessage and WORequest expect all
headers to be lower-case - and that the WOServletAdaptor does not
make sure all headers are lower-case. This results in posts from a
form whose enctype is "multipart/form-data" failing to update any
of the variables bound to form fields. Steps to Reproduce: 1.
Create a new WebObjects project 2. Modify the main component as
follows: HTML: <wo:WOForm> <wo:WOTextField value = "[message]"></
wo:WOTextField> <wo:WOSubmitButton action = "[sayHello]"></
wo:WOSubmitButton> </wo:WOForm> <wo:WOForm enctype = "multipart/
form-data"> <wo:WOTextField value = "[message]"></wo:WOTextField>
<wo:WOSubmitButton action = "[sayHello]"></wo:WOSubmitButton> </
wo:WOForm> <wo:WOString value = "[message]"></wo:WOString> Java:
public String message; public Main(WOContext context)
{ super(context); } public WOComponent sayHello() { message =
"hello, " + message + "!"; NSDictionary headers =
this.context().request().headers(); for(int
i=0;i<headers.allKeys().count();i++) { String header = (String)
headers.allKeys().objectAtIndex(i); System.out.println(header + ":
"); System.out.println(headers.valueForKey(header));
System
.out.println(this.context().request().headerForKey(header)); }
return(this); } 3. Build the application as both a .woa and a .war
4. Deploy the applications. Expected Results: Type something in the
forms and click on sumbit. Both forms should behave in the same way
and you should see "hello, " plus whatever you typed. The console
should show all the headers with the values repeated. Actual
Results: When a WebObjects application is deployed in a servlet
container, the following rather strange situation occurs: When this
is deployed as a .woa, it produces the following correct output:
<snip> content-type: ( multipart/form-data; boundary=----
WebKitFormBoundaryZdrwLAre6TArzAid ) multipart/form-data;
boundary=----WebKitFormBoundaryZdrwLAre6TArzAid </snip> But when it
is run in a servlet container, it produces the following, obviously
incorrect output: <snip> Content-Type: ( multipart/form-data;
boundary=----WebKitFormBoundaryonU48QK5I46+pA1T ) null </snip> A
problem exists because the valueForHeader() method in WOMessage
assumes all headers are lower-case, so when WORequest attempts to
determine if the request isMultipartFormData(), it does so by
asking for the contentType() - which results in a call to
valueForHeader(), which in turn calls the get() method of the
underlying TreeMap of _httpHeaders, but mistakenly does so with a
lower-case version of the key:
(List)_httpHeaders.get(aKey.toString().toLowerCase()) The result of
all of this is that if you specify the "enctype" of your form as
"multipart/form-data" none of the bindings for your form will get
values.
Whilst this is reported as fixed, I'm still using a work-around in
my app (as I haven't upgraded it to a fixed version of WO yet) - so
if this is the bug you're encountering, the work-around might help
you too.
I wrote a subclass of WOServletAdaptor that converts all the header
keys to lowercase before calling 'super'. You just need to include
this class in your project and modify the web.xml that is created to
reference your WOServletAdaptor subclass instead of the default one.
MyServletAdaptor.java:
package au.id.jmacmullin;
import java.io.IOException;
import javax.servlet.ServletException;
import com.webobjects.jspservlet.WOServletAdaptor;
public class MyServletAdaptor extends WOServletAdaptor {
public MyServletAdaptor() throws ServletException {
super();
}
// over-rides the default implementation to first convert all the
header keys to lower-case, before calling super
public void doPost(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response) throws
IOException, javax.servlet.ServletException {
LowercaseHeaderKeysWrapper requestWrapper = new
LowercaseHeaderKeysWrapper(request);
super.doPost(requestWrapper, response);
}
}
LowercaseHeaderKeysWrapper.java:
package au.id.jmacmullin;
import java.util.Enumeration;
import java.util.Vector;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class LowercaseHeaderKeysWrapper extends
HttpServletRequestWrapper {
public LowercaseHeaderKeysWrapper(HttpServletRequest request) {
super(request);
}
public Enumeration getHeaderNames() {
Vector headerNames = new Vector();
Enumeration existingNames = super.getHeaderNames();
while(existingNames.hasMoreElements()) {
headerNames.add(((String)
existingNames.nextElement()).toLowerCase());
}
return(headerNames.elements());
}
public Enumeration getHeaders(String name) {
Enumeration returnVals;
// try and find a header with the exact name
Enumeration existingHeaders = super.getHeaders(name);
if(existingHeaders!=null && existingHeaders.hasMoreElements()) {
returnVals = existingHeaders;
} else {
StringBuilder sb = new StringBuilder();
// try and find a header with different capitalisation
String[] words = name.split("-");
for(int i=0;i<words.length;i++) {
sb.append(words[i].substring(0, 1).toUpperCase());
sb.append(words[i].substring(1));
if(i<words.length-1) {
sb.append("-");
}
}
String camelCaseHeaderKey = sb.toString();
returnVals = super.getHeaders(camelCaseHeaderKey);
}
return(returnVals);
}
}
web.xml:
...
<!-- The WebObjects Servlet that interfaces between the Servlet
container
world and the WebObjects world. -->
<servlet>
<servlet-name>MyServletAdaptor</servlet-name>
<servlet-class>au.id.jmacmullin.MyServletAdaptor</servlet-class>
<load-on-startup>5</load-on-startup>
</servlet>
...
Hope this helps,
Jake
On 31/10/2008, at 8:11 AM, Chuck Hill wrote:
On Oct 30, 2008, at 12:30 PM, William Hatch wrote:
5.4.3, using a pretty recent Wonder build. Deployed under either
tomcat or as regular .woa, development in Eclipse....
Nothing happens when I click "Upload".
Meaning no request to the server? A request to the server but no
data sent? Data is sent but the component does not see it?
Something else?
I came across a thread by Mike discussing the perils of not
binding filePath along with data, and that's not the case here;
both are bound, although filePath is completely not used. This
same exact component worked fine in 5.3. I also came across some
other scary posts regarding encoding, and one regarding
WOServeletAdaptor issues with WOFileUpload under 5.4 So what's the
new new trick for getting this to fly again?
I don't recall having problems with uploads moving an app from
5.3.3 to 5.4.3.
Chuck
--
Chuck Hill Senior Consultant / VP Development
Practical WebObjects - for developers who want to increase their
overall knowledge of WebObjects or who are trying to solve specific
problems.
http://www.global-village.net/products/practical_webobjects
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden