• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Reading POST data in different types of servlets?

Alex Lieb
Ranch Hand
Posts: 54
Java Netbeans IDE Notepad
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm trying to learn some stuff about Ajax for work. The way I understand it there's multiple ways to send data to the back end with an XMLHttpRequest/ActiveX object; you can use just the servlet in a JSP page by sending it to a JSP page which processes it in scriptlets, or you can post it directly to the back end via a servlet mapped to a URL.

The JSP page version of this went swimmingly; it posts it back with POST, gets the BufferedReader object out of the request, turns it into a string, does business logic, sets the headers on the response object, and the function tied to the "readystatechange" event reads the headers and sends them back to the view component. Blam. There and Back Again, an XMLHttpRequest's Tale. I'm a little confused about how it even registers the response object, because at no point in that process do I actually tell it to post the response back to the source, but somehow it knows when the servlet is done executing, and it's able to look at the response object when it does. BUT that isn't actually why I'm here.

I'm here because in theory that entire process should work exactly the same if you send the request object to a servlet on the back end directly, but it doesn't. And I've figured out *exactly* where it's breaking, but after several hours of combing through the debugger and googling I still have no idea why it's breaking at that point. For some reason the BufferedReader thinks the byteArray is completely empty, but I know it's not; I went into the request object in the debugger and I found those goddamn bytes, and they represent the correct values, but somehow they're getting lost when "request.getReader();" is executed.

This is the code that reads the input stream in the JSP page:

The POST method in this case is only posting back one variable, so I don't have to do any string manipulations after this aside from verifying that ID can actually be safely parsed as an integer.

So, this is how the code looks in the servlet on the back end:

It's exactly the same, but for some reason this time it can't find anything in the byte array. I checked the debugger to see if the bytes are actually there. They are in the request object when it's passed through as a parameter, so they *are* making it to the servlet, but for some reason it's not reading them right. I found the bytes in the request object under POST data in the request object, and they're there in the servlet's request object too. After request.getReader executed, I checked it to make sure it wasn't losing the bytes in transmission there either. The inputstream byte array object in that one has 500 rows, I read them all manually and found that most of it is just headers, but then there's a few spaces and the actual post data is in byte #540. So it's definitely there, and there's also a property of the inputstream that says "start" and "end", and they both say 541. So since the index starts at 0 that would mean index 540. So I know it knows where to look. Unless it actually means index 541, in which case something has already read the POST data, and it thinks it's done.

Just for kicks I tried it this way too, just to see if the problem was associated with how I was using getReader, but it messes up in the exact same way when you do it this way:

Both of those code snippets compile and execute without throwing errors, but they both set ID to null.

I'm going to continue trying things as I think of them, but at this point I really am getting close to being out of ideas for what could be causing this. I tried reading the data in by getting the InputStream instead of using getReader, but that causes the exact same problem, strangely, which tells me that the issue is probably related to the inputstream object, not the reader object. I know it would probably be easier to just use GET, but the entire reason I'm doing this particular project is so I can learn stuff in order to help out with a project slated to start at some point in the future, so for the sake of learning I need to figure out how to make it work using POST.

There is one other possibility I've considered but don't know how to verify: This project uses struts 1.3.5. In the JSP page example, it's sending the request to the JSP page and using it as a servlet, but there's no external mapping help taking place. In the servlet on the back end, it's passing it to a mapped address. Mapping to a servlet listed in the web.xml doesn't work because it barfs and wants it to be in the struts-config, and making it a struts config object means your servlet class has to accept an action Mapping object as a parameter, so it's not a normal servlet, it's a struts action servlet. I'm not trying to read from the mapping or the form, so it shouldn't make any difference, but I don't know exactly how struts maps stuff, so hey, maybe it messes with the request object in a way normal Http requests don't? If struts tries to preprocess it and put it into a bean, I could see a scenario in which it thinks it's already read it, and won't read it again, but I'm not sure how to verify if that's happening. Probably not, but in case it's relevant, I'm throwing that out there.

So I'm pretty baffled by this. There's no huge rush to figure it out because I'm actually ahead of schedule with the stuff at work, which is nice, but this is kind of the last thing on my short-term "hey, learn how to do this so you can help with this stuff" list. Apparently we won't be ready to actually start working on the next leg of the project for a while, but of all the bugs I've encountered so far this is both the most innocent-looking one and the one that's taken me the longest to figure out.

Also, I don't think the problem is in the javascript, because the data is definitely arriving in the servlet intact, but just in case, here's the javascript that sends the request too:

EDIT: JESUS CHRIST. I can't believe I spent 5 hours on this one bug just to have the solution be:

1) Something this stupidly simple

2) Something I've been considering as a possibility for hours, but hadn't actually tried yet.

I feel like I just spent half a day beating ants to death with a giant hammer only to discover that I had a can of bug spray on me the whole time.

So yeah, what I said earlier about struts is totally what's going on here.

When Struts gets request objects, it handles them by automatically populating a bean with data corresponding to the fields. So of course, it's getting this post data and going "Oh look! Post data! I know what to do with this, let me help you!", and it tries to put it into a bean, but because I'm sending this request from javascript, of course that doesn't work, so it basically just deposited several bytes of useless garbled nonsense into a bean; into what properties I haven't the faintest idea, seeing as the post data wasn't connected to any struts elements with ID's that the dispatcher could try to match them up with. And of course, because reading POST data is like James Bond getting mission instructions, by the time it got to the servlet, *it was still in the request object* somehow (which is what really confuses me; after it gets there it should be done.)

So yeah, in case anyone else runs into this, this is how I fixed it;

I turned this:

Into this:

No bean. No input source listed. No automatic bean population. Struts stops reading my mail / stops intercepting POST data.
Tony Docherty
Posts: 3040
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Have a cow for posting a good question and then having found the solution yourself for coming back to answer it in such detail. Hopefully your solution will help others in the future.
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic