Hi Marko

Great stuff, and it will only become better once JAX-RS 2.1 and new MVC spec get released and combined :-)

Thanks, Sergey

On 20/04/15 13:33, Voss, Marko wrote:
Hi Sergey,

yes, it works now by injecting the HttpServletRequest and -Response as 
parameters. I do not know, why it did not work the first time.

Maybe I really put the @Context in the implementation instead of the 
interface... I do not remember. :-)


Have a nice day Sergey and thank you for your continuous help!

Best regards,
Marko

-----Ursprüngliche Nachricht-----
Von: Sergey Beryozkin [mailto:[email protected]]
Gesendet: Freitag, 10. April 2015 12:01
An: [email protected]
Betreff: Re: AW: How to forward requests to a JSP page when using 
CXFNonSpringJaxrsServlet

Hi,
I had a quick check yesterday, I have a test where one of JAX-RS contexts is 
injected into a field and it depends on Java Proxy/InvocationHandler.
InvocationHandler is not invoked when a field proxy is simply passed somewhere 
else as by reference, so there's no way (I can't see any way to be more precise 
:-)) of using this latest code with NetWeawer.

A thread local HttpServletRequest proxy implements HttpServletRequest interface 
but apparently it is not sufficient with NetWeaver. Note, the exception message 
may be misleading, it may well be nothing to do with the fact a thread local 
proxy is passed further, but rather to do with some class loader issue specific 
to NetWeaver

So if you'd like to use this code then inject the contexts as parameters, in 
the short term at least

Sergey



On 09/04/15 14:52, Sergey Beryozkin wrote:
Hi

OK, this explains it then. So the injected request and response
proxies are passed further by reference.

I guess NetWeaver is not using a base HttpServletRequest in the
assignment/cast, otherwise it would likely not be a problem at all.

Hmm... Unless this basic Java reference action can not be handled at a
proxy level then it would not work... Using RequestDispatcherProvider
in a dynamic mode is much simpler for sure :-).

I'll investigate and see if anything can be done here at all...

Re Context in method signatures - the only reason I can see why it
does not work in your case is that you have an interface and the
implementation - you need to put all the JAX-RS annotations on the
interface methods, instead of some annotations on the interface and
some
- on the implementation, otherwise a JAX-RS rule that the annotations
are not inherited once a given method has some of them works, often
resulting in non-functional endpoints

Sergey


On 09/04/15 14:31, Voss, Marko wrote:
Hi Sergey,

this is the code I am using:

@Context
private ServletContext servletContext;

@Context
private HttpServletRequest servletRequest;

@Context
private HttpServletResponse servletResponse;

@Override
public Response logon() {
     try {

this.servletContext.getRequestDispatcher(url).forward(this.servletReq
uest,
this.servletResponse);
     } catch (Exception e) {
         throw new WebApplicationException(e);
     }
     return null;
}

I have to use @Context resources as class fields because of using
@Context on method parameters does not work. The JAXRS endpoints will
not exist then for methods like that. I do not know why.


Best regards,
Marko

-----Ursprüngliche Nachricht-----
Von: Sergey Beryozkin [mailto:[email protected]]
Gesendet: Donnerstag, 9. April 2015 15:09
An: [email protected]
Betreff: Re: How to forward requests to a JSP page when using
CXFNonSpringJaxrsServlet

Hi Marko,

no problems, that does not clear things up though, except that it
points to the fact that may be you use

@Context
HttpServletRequest request;

request.getServletContext().getRequestDispatcher() ?

I can not connect a reference to ThreadLocalHttpServletRequest with
the earlier code you posted otherwise, where you showed
ServletContext being injected...If ServletContext is to be injected
then the runtime does not create ThreadLocalHttpServletRequest at all.

if it is the case then I'll need to enhance the solution to 1. to
intercept request.getServletContext() calls.

But I've realized you do not have to wait for a snapshot in order to
check why the exception is raised. Unfortunately I'm still not sure
why a cast to ThreadLocalHttpServletRequest is attempted. Assuming
you do have HttpServletRequest injected then what I said earlier
about thread locals applies the same way...

You might want to pass contexts as JAX-RS method parameters which
would avoid creating thread locals at the cost of making the
signatures more verbose, but I'm curious why you have an exception if
the context is injected into a field

Cheers, Sergey

On 09/04/15 13:53, Voss, Marko wrote:
Hi Sergey,

I can test the SNAPSHOT by tomorrow at the earliest because of our
artifactory is not updating before tonight. I rebuild the code to
reproduce the ClassCastException.

Looks like I remembered that message the wrong way. I am sorry. :-)

This is a ClassLoader issue:


WARNING: javax.ws.rs.WebApplicationException:
java.lang.ClassCastException: class
org.apache.cxf.jaxrs.impl.tl.ThreadLocalHttpServletRequest:foo.bar/C
at
aloguefactory_...@com.sap.engine.boot.loader.ResourceMultiParentClas
sL oader@5125c637@alive incompatible with class
com.sap.engine.services.servlets_jsp.server.runtime.client.HttpServl
et
RequestFacadeWrapper:service:[email protected].
Re sourceMultiParentClassLoader@477afcff@alive
at
foo.bar.logon.web.jaxrs.impl.LogOnServiceImpl.logon(LogOnServiceImpl
.j
ava:70)

LogOnServiceImpl is the JAXRS service we are talking about the whole
time. CatalogueFactory_ear has absolutely nothing to do with this
service at this point and I have no idea, why this is even being
mentioned here. LogOnServiceImpl is in another EAR. The issue is,
that the HttpServletRequestFacadeWrapper for JSP pages provided by
NetWeaver cannot be castet to the ThreadLocalHttpServletRequest of
CXF, which makes sense.


Does this change the issue?


Best regards,
Marko

-----Ursprüngliche Nachricht-----
Von: Sergey Beryozkin [mailto:[email protected]]
Gesendet: Donnerstag, 9. April 2015 11:40
An: [email protected]
Betreff: Re: AW: AW: AW: AW: How to forward requests to a JSP page
when using CXFNonSpringJaxrsServlet

Hi,
sure, it is done, what I'd like to ask you though is to test a
snapshot, The fix I did is basically about wrapping a returned
RequestDispatcher and setting the property checked by CXF in a
couple of places.

I'm actually not sure why you saw a class cast exception with Option
1 before my fix. Copying the relevant text here:

    >>>>>> 1.      I tried to implement the forwarding as it was
already done
    >>>>>> by the old servlet using:
    >>>>>>
    >>>>>> @Context
    >>>>>> private ServletContext context;
    >>>>>>
    >>>>>> context.getRequestDispatcher(url).forward(request,
response);  >>>>>>  >>>>>> But this does not work, because of a
ClassCastException happening.
    >>>>>> The exception message was like: The ThreadLocal instance
for  >>>>>> ServletContext could not be casted to the
RequestDispatcher  >>>>>> instance, which is provided by the server.
(NetWeaver)  >>>>>>  >>>>>> The ThreadLocal object is provided by
CXF and the  >>>>>> RequestDispatcher implementation is provided by
NetWeaver. Of  >>>>>> course, this will not work.

I'm not sure I understand to be honest. The thread local object
provided by CXF keeps current ServletContext objects (created by
NetWeaver I assume). So the runtime will do

threadLocal.put(currentServletContext)

and then

context.getRequestDispatcher(url)

is effectively

((ServletContext)threadLocal.get()).getRequestDispatcher(url)

so I'm not sure where ClassCastException is coming from...

Please investigate on your end by debugging the code...

Cheers, Sergey




On 09/04/15 07:24, Voss, Marko wrote:
Hi Sergey,

yes, we use a 2.7.x CXF version. I think, that is because of the
old NetWeaver server we have to use. Can you please fix this for
2.7.16 as well? Thank you very much. :-)


Best regards,
Marko

-----Ursprüngliche Nachricht-----
Von: Sergey Beryozkin [mailto:[email protected]]
Gesendet: Mittwoch, 8. April 2015 18:59
An: [email protected]
Betreff: Re: AW: AW: AW: How to forward requests to a JSP page when
using CXFNonSpringJaxrsServlet

Hi Marko

See https://issues.apache.org/jira/browse/CXF-6337

Can you please test either 3.0.5-SNAPSHOT or 3.1.0-SNAPSHOT ?
Do you need it for CXF 2.7.16 ?

Sergey

On 08/04/15 13:31, Sergey Beryozkin wrote:
Hi Marko

That should be possible to get fixed.
As I said, the query parameters are passed along either way but if
you can not modify JSP or these query parameters are actually
representing some custom parameters, then yes, I can see why
option
1 makes sense.

By the way, RequestDispatcher supports dynamic resource paths set
on the message context, so if you have CXF MessageContext injected
then you'd set a property on it,

"redirect.resource.path"="my.jsp?a=b"

and it will work, but it is very much CXF specific....

I'll try to get option 1 done before the releases...

Cheers, Sergey

On 08/04/15 13:13, Voss, Marko wrote:
Hi Sergey,

yes, it would be great, if variant 1 would work fine. (No
ClassCastException)

servletContext.getRequestDispatcher("my.jsp?a=b").forward()


Is it possible to fix this?


Best regards,
Marko


-----Ursprüngliche Nachricht-----
Von: Sergey Beryozkin [mailto:[email protected]]
Gesendet: Mittwoch, 8. April 2015 14:07
An: [email protected]
Betreff: Re: AW: AW: How to forward requests to a JSP page when
using CXFNonSpringJaxrsServlet

Hi

Not at the moment, how does it work in general, is it

servletContext.getRequestDispatcher("my.jsp?a=b").forward() ?

Note that RequestDispatcherProvider sets query parameters (as
well as path and other request properties) as HttpServletRequest
parameters, see

https://fisheye6.atlassian.com/browse/cxf/rt/frontend/jaxrs/src/m
ai
n
/
java/org/apache/cxf/jaxrs/provider/RequestDispatcherProvider.java
?r
=
3
309231e467225b18b24d90d77153a0c572a17e0#to342


Cheers, Sergey

On 08/04/15 12:37, Voss, Marko wrote:
Hi Sergey,

can I somehow tell the RequestDispatcher to use the String of
the Response Entity for redirection? Just saw, that there are
also query parameters added to the JSP URL in some cases...


Thanks and best regards,
Marko

-----Ursprüngliche Nachricht-----
Von: Sergey Beryozkin [mailto:[email protected]]
Gesendet: Mittwoch, 8. April 2015 13:03
An: [email protected]
Betreff: Re: AW: How to forward requests to a JSP page when
using CXFNonSpringJaxrsServlet

Hi Marko

This is one way to do it, yes, does not even has to be on the
same line, example,
org.apache.cxf.jaxrs.provider.RequestDispatcherProvider
(
resource.Status.JSP1=/hello.jsp
resource.Status.JSP2=/foo.jsp
)

Perhaps another alternative is to wrap an enum value into a bean
class and redirect to a single JSP resource, which will get the
bean, check the enum, delegate to specific JSPs...

Cheers, Sergey

On 08/04/15 06:47, Voss, Marko wrote:
Hello Sergey,

variant 2 was just an idea but is not really helpful, because
of we need to do some logic in order to decide, which JSP to call.
So we have to execute some code.

So the idea I got is the following: The servlet does execute
the code and returns an enum value. Based on the enum value,
the RequestDispatcher decides, which JSP to call. This might
look like
this:

org.apache.cxf.jaxrs.provider.RequestDispatcherProvider(resource.
S
t
at
u
s.JSP1=/hello.jsp
resource.Status.JSP2=/foo.jsp)

The Response object gets the enum value as its entity.

Is this correct?


Thank you very much and best regards,

Marko

-----Ursprüngliche Nachricht-----
Von: Sergey Beryozkin [mailto:[email protected]]
Gesendet: Dienstag, 7. April 2015 17:40
An: [email protected]
Betreff: Re: How to forward requests to a JSP page when using
CXFNonSpringJaxrsServlet

Hi,

Please see comments below
On 07/04/15 14:42, Voss, Marko wrote:
Hello,

I do have the following situation:

We have to use the CXFNonSpringJaxrsServlet for implementing
the REST endpoints.

The main servlet (old code to be replaced by the new REST
endpoints) of the application does implement internal
forwarding to JSP pages.
(for example to a login page)


1.      I tried to implement the forwarding as it was already done
by the old servlet using:

@Context
private ServletContext context;

context.getRequestDispatcher(url).forward(request, response);

But this does not work, because of a ClassCastException happening.
The exception message was like: The ThreadLocal instance for
ServletContext could not be casted to the RequestDispatcher
instance, which is provided by the server. (NetWeaver)

The ThreadLocal object is provided by CXF and the
RequestDispatcher implementation is provided by NetWeaver. Of
course, this will not work.
Hmm, interesting, may make sense supporting this variation,
I'll have a look...



2.       I was trying to use the RequestDispatcherProvider of CXF,
but how can you configure this provider using the
CXFNonSpringJaxrsServlet?

<servlet>
                     <servlet-name>RestfulApp</servlet-name>

<servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsS
er
v
l
et</servlet-class>

                     <init-param>

<param-name>jaxrs.serviceClasses</param-name>
                            <param-value>
                            ...
                            </param-value>
                     </init-param>
                     <init-param>

<param-name>jaxrs.providers</param-name>
                            <param-value>

org.apache.cxf.jaxrs.provider.RequestDispatcherProvider
                            <!-- How to configure this one
here??? -->
                            </param-value>
                     </init-param>
                     <load-on-startup>1</load-on-startup>
               </servlet>


The simplest way to do at a servlet level is to use redirect
parameters, see

https://git-wip-us.apache.org/repos/asf?p=cxf.git;a=blob;f=syst
es
t
s
/j
a
xrs/src/test/resources/jaxrs_dispatch/WEB-INF/web.xml;h=a221233
7b
d
6
a9
e
d7a212b21a6826850581601121;hb=HEAD

or indeed you can directly configure this provider (and other
providers) as a parameter, do something like

org.apache.cxf.jaxrs.provider.RequestDispatcherProvider(resourc
eP
a
t
h=
/
WEB-INF/jsp/test.jsp
someotherproperty=somevalue)



3.       I was trying to implement a RequestHandler, which worked
but when the forwarding happens, I get spammed by error
messages on server side, that the OutputStreams of the
servlets are already taken by a getWriter() method. This spam
should be avoided.
Example
Spam:

WARNING: Interceptor for
{http://impl.jaxrs.web.foo.bar/}MyServiceImpl has thrown
exception, unwinding now
com.sap.engine.services.servlets_jsp.server.exceptions.WebIllegalStateException:

The stream has already been taken by method [getWriter()].
at
com.sap.engine.services.servlets_jsp.server.runtime.client.Htt
pS
e
r
vl
e
tResponseFacade.getOutputStream(HttpServletResponseFacade.java
:2
4
4
)

This servlet is not in use at all at this point of the request
and not after the request as well. So I wonder in general, why
this exception occurs on this servlet. It is maybe a NetWeaver
thing.


4.       I was trying to implement an equivalent to the
RequestDispatcherProvider, doing things here by code. But even
when this works, I still get the spam from above.

In both cases the outbound CXF JAX-RS interceptor and Http
transport need to know the request has been redirected, this
can be done by setting an "http.request.redirected" property on
the current message,

message.put("http.request.redirected", true)

But the option 2 is simpler, can you try it and let me know if
it works for you ?

Thanks, Sergey


Any help is much appreciated.


Best regards,

Marko







--
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com






Reply via email to