2

Background information: I have a file upload applet in my jsf page. This applet expects an adress where it can send it's POST request. (I can't edit this post request to add more fields or something). The post method of my servlet then stores the file. This job can't be done by a managed bean because the servlet has to be annotated with @MultiPartConfig and I can't add this annotation to the jsf managed bean. In order to force the upload applet to use the same session I added an URL attribute named jsessionId to the post request according to this post. In my servlet I am now able to access session scoped beans.

Now I have a ViewScoped bean where I store some form input data which I want to use in the servlet, since adding those inputs to the post request doesn't work (Applet is a third party project (JUploadApplet) and for some reason it doesn't work to add additional form data). Now is it possible to access the ViewScoped bean from within the servlet ? If I change the scope into SessionScope I am able to process the input but with ViewScoped I get a NullPointerException if I try to access the bean like this : UploadBean uploadBean = (UploadBean)request.getSession().getAttribute("uploadBean");

Community
  • 1
  • 1
nico1510
  • 606
  • 9
  • 29

1 Answers1

6

This is not possible. Your best bet is to let the view scoped bean generate an unique key, store itself in the session scope by that key and pass that key as additional parameter to the applet and finally let the servlet access the session attribute by that key.

E.g.

private String sessionKey;

@PostConstruct
public void init() {
    sessionKey = UUID.randomUUID().toString();
    FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(sessionKey, this);
}

@PreDestroy
public void destroy() {
    FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(sessionKey);
}

Let the applet pass the sessionKey as request parameter to the servlet, so that the servlet can do

String sessionKey = request.getParameter("sessionKey");
Bean bean = (Bean) request.getSession().getAttribute(sessionKey);
// ...

Note that instead of the bean itself, you can also just store an arbitrary bean/valueobject/etc.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • ok but I don't exactly know how to pass the request parameter to the servlet. I tried adding it to the postURL parameter like this : but this won't work – nico1510 Jan 08 '13 at 15:39
  • Your URI syntax is wrong. You need the `?` character to separate the URI query string from the URI path. The `&` character is only to separate multiple parameters in the query string. – BalusC Jan 08 '13 at 15:41
  • your solution almost works but there's still a (strange) problem : I put an object (a HashMap) into the SessionMap as you described above. Now when I upload one file everything works fine, but as soon as I try to upload a second file the attribute is not found anymore. Could this have something to do with the PreDestroy method ? I already checked by debugging that a new ViewScoped Bean is created so I'm not using the same View and hence not the destroyed bean. – nico1510 Jan 08 '13 at 17:23
  • At first I got NullPointerExceptions but when I try to reproduce this bug now I only get the warning WARNING: PWC4011: Unable to set request character encoding to UTF-8 from context /webschemex, because request parameters have already been read, or ServletRequest.getReader() has already been called – nico1510 Jan 08 '13 at 17:23
  • That the view scoped bean is recreated is actually a different problem. It's likely related to the way how your view is markup and/or how you're navigating. As to PWC4011, check this answer: http://stackoverflow.com/questions/7643484/how-do-i-get-rid-of-annoying-message-on-output-log-pwc4011-servletrequest-getr – BalusC Jan 08 '13 at 17:25
  • No sorry I said something misleading... I meant a ViewScoped bean is created when I open a new View so this works fine and can't be the cause of my problem. However I have the feeling that the part in my jsf page where the applet is placed is only loaded once. I added the param to the postURL param like this but this only works once. I also tried to add just a String as parameter but even this String I can only retrieve once... – nico1510 Jan 09 '13 at 13:34
  • Hmm, interesting. What if you remove predestroy? – BalusC Jan 09 '13 at 13:37
  • I even completely removed the code where I put an object into the sessionmap and now the only code I have in my application is the following. I append (for test purposes) an attribute named "nodename" to the URL like this : http:XXXXXXXX/request;jsessionid=#{session.id}?nodename=#{uploadBean.name}" /> and name is just a String in the viewscoped uploadBean. I can however only retrieve this String once in my servlet. It's the same problem like I had with putting an object into the sessionmap and removing it after the bean is destroyed so the bug has to be caused by another reason.. – nico1510 Jan 09 '13 at 15:21
  • Oh, you mean that the `request.getParameter("sessionKey")` returns `null` in subsequent requests on the servlet? Well, that's most likely a bug in the applet. Your best bet is probably to use a fixed session attribute key instead which is known by both the bean and the servlet, so that you don't need to pass it through. This may however have undesirable side effects when the same page is opened in multiple browser tabs/windows. – BalusC Jan 09 '13 at 15:27
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/22470/discussion-between-polofan-and-balusc) – nico1510 Jan 09 '13 at 16:21
  • But the only task the applet has to do with this postURL parameter is to pass it through, to the servlet. Basically it doesn't have to parse it or anything right? It's strange that this causes a bug then – nico1510 Jan 09 '13 at 17:10
  • Yes, that was also my expectation. But the observation and the symptoms tells otherwise, right? To reiterate, the request parameter returns `null` in the servlet on second and subsequent calls from the applet, right? Perhaps the applet is refreshing/updating the page in some way? – BalusC Jan 09 '13 at 17:11
  • I think I found the bug but still I need a little of your help. In order to let the applet know that the file upload was successful it expects an answer from the servlet, too. Now in my servlet code I therefore have the line : response.getWriter().println("SUCCESS"); but for some reason, on subsequent post requests the response body consits of the whole Html Code of the last page where the servlet sends an redirect. Therefore the response doesn't contain the word "success" anymore. I also close the writer after printing the word success so this can't be the problem... – nico1510 Jan 10 '13 at 11:03
  • Is the same servlet used for more other things than processing the file upload? To exclude one and other, do you see `IllegalStateException` in server logs? Well, at that point it's hard to tell where's the problem. Perhaps in one of the filters? Perhaps in servlet's logic? Stepping through the servlet's code in a debugger may give clues. – BalusC Jan 10 '13 at 12:13
  • Since this has nothing to do with the original topic I'm going to create a new one where I can paste the debug log from the servlet I think this will help. I did however find out, that without the parameter jsessionID I am able to upload more than 1 file (Of course other things don't work without this parameter so I need it) Topic : http://stackoverflow.com/q/14258745/1644061 – nico1510 Jan 10 '13 at 13:12
  • Is `preRenderView` still early enough to set the session value? – djmj Aug 05 '13 at 15:18
  • Does not seems so and needing a `f:viewParam` value within the servlet needs to manually invoke the conversion from raw request parameter to the targeted instance. – djmj Aug 05 '13 at 22:24