Great, thanks to give us feedback!

*Romain Manni-Bucau*
*Twitter: @rmannibucau <https://twitter.com/rmannibucau>*
*Blog: **http://rmannibucau.wordpress.com/*<http://rmannibucau.wordpress.com/>
*LinkedIn: **http://fr.linkedin.com/in/rmannibucau*
*Github: https://github.com/rmannibucau*



2013/2/8 Chet Hosey <[email protected]>

> Success!
>
> UriInfo is now using the HTTP request info, both through HTTP and AJP.
> I've confirmed with apache-tomee-1.5.2-20130208.041201-63-jaxrs. Absolutely
> no configuration changes were needed, either. I unpacked the snapshot,
> copied the test app to webapps/, ran bin/startup.sh, and tested.
>
> This is exactly the behavior I'd expected initially, and should allow
> JAX-RS UriInfo to work through HTTP and AJP load balancers on TomEE.
>
> Thank you!
>
> -- Chet
>
> On Feb 7, 2013, at 9:08 AM, Romain Manni-Bucau <[email protected]>
> wrote:
>
> > oh think i misunderstood, in fact you want the input value so potentially
> > the load balancer value, not always the ajp info right?
> >
> > so i hope my fix will help
> >
> > *Romain Manni-Bucau*
> > *Twitter: @rmannibucau <https://twitter.com/rmannibucau>*
> > *Blog: **http://rmannibucau.wordpress.com/*<
> http://rmannibucau.wordpress.com/>
> > *LinkedIn: **http://fr.linkedin.com/in/rmannibucau*
> > *Github: https://github.com/rmannibucau*
> >
> >
> >
> > 2013/2/7 Chet Hosey <[email protected]>
> >
> >> AJP isn't generally exposed to the client at all.
> >>
> >> A typical configuration might include a web server such httpd or IIS
> >> listening on a public IP on port 80, and several Tomcat instances
> running
> >> AJP on private IP addresses. The web server is configured to route
> certain
> >> requests (like /appname/*) to a running Tomcat instance via AJP. If
> >> sessions are clustered, or the conversations are stateless, an
> >> administrator shut down an individual Tomcat instance without impacting
> >> external users.
> >>
> >> So a REST request would be made over HTTP (or HTTPS) to the web server,
> >> and routed to one of the Tomcat instances over AJP. There's nothing
> special
> >> about REST that makes AJP inappropriate; it's just a way of connecting a
> >> web server to Tomcat. But please consider an HTTP load balancer running
> on
> >> port 80, and sending requests to internal Tomcat instances running on
> ports
> >> 8080, 8081, etc. The client will send requests to port 80. But none of
> >> Tomcat servers' connectors will be bound to the same port. It would
> similar
> >> to AJP, in that the public port doesn't match the Tomcat connectors'
> listen
> >> ports. And all communication would be over HTTP.
> >>
> >> Even with requests over AJP, for example, a REST method can get an
> >> injected HttpServletRequest object. My test code demonstrates that.
> This is
> >> why I believe that the right behavior for UriInfo would be to match the
> >> behavior of the HttpServletRequest object. It generally works
> >> out-of-the-box, and there are already ways for an administrator to
> override
> >> the values returned by HttpServletRequest without having to alter the
> >> application.
> >>
> >> I'll try the latest snapshot, and put the AJP connector first as you
> >> advise. Please consider, though, that the correct public host / port may
> >> never match a connector's configuration, and that it may be better for
> >> UriInfo to get these values from an HttpServletRequest than to check the
> >> connectors.
> >>
> >> Thanks!
> >>
> >> On Feb 7, 2013, at 8:14 AM, Romain Manni-Bucau <[email protected]>
> >> wrote:
> >>
> >>> updated as possible as it was this feature
> >>>
> >>> can you try with the next snapshot please?
> >>>
> >>> where i doubt is when using ajp protocol you don't really respect REST
> >>> specification which relies on http only.
> >>>
> >>> *Romain Manni-Bucau*
> >>> *Twitter: @rmannibucau <https://twitter.com/rmannibucau>*
> >>> *Blog: **http://rmannibucau.wordpress.com/*<
> >> http://rmannibucau.wordpress.com/>
> >>> *LinkedIn: **http://fr.linkedin.com/in/rmannibucau*
> >>> *Github: https://github.com/rmannibucau*
> >>>
> >>>
> >>>
> >>> 2013/2/7 Romain Manni-Bucau <[email protected]>
> >>>
> >>>> Hmm, the point is it needs to select the connector to use for
> deployment
> >>>> (to compute the base address)...not sure of a clever way here
> >>>>
> >>>> Can you try to define ajp connector first in server.xml please?
> >>>> Le 7 févr. 2013 08:24, "Chet Hosey" <[email protected]> a écrit
> :
> >>>>
> >>>> To say that it's "deployed on HTTP" is inaccurate. It's deployed on
> >>>>> Tomcat, which TomEE is built around, and which provides more than one
> >> type
> >>>>> of connector.
> >>>>>
> >>>>> It's common to use httpd in front of Tomcat to serve static content,
> >>>>> balance between multiple workers, etc. It's reasonable that AJP
> support
> >>>>> might not be ready yet or might have been overlooked.
> >>>>>
> >>>>> The statements on the project's website suggest that the goal is to
> add
> >>>>> features to Tomcat without sacrificing functionality:
> >>>>>
> >>>>> - Goal: "Simple, Get more from Tomcat without giving anything up."
> >>>>> - Focuses: "Don't mess with Tomcat"
> >>>>> - TomEE doesn't "include Tomcat in some truncated and stripped-down
> >> form"
> >>>>> - With TomEE, there's "no picking and choosing individual parts of
> >> Tomcat
> >>>>> and building a 'new' server leveraging Tomcat."
> >>>>>
> >>>>> With such strong language, it would be surprising if the project
> didn't
> >>>>> plan to support AJP connections as it does HTTP.
> >>>>>
> >>>>> Might this be addressed in a future release? Can you suggest ways to
> >>>>> contribute?
> >>>>>
> >>>>>
> >>>>> On Feb 6, 2013, at 5:40 PM, Romain Manni-Bucau <
> [email protected]>
> >>>>> wrote:
> >>>>>
> >>>>>> because the REST service is deployed on HTTP not AJP
> >>>>>>
> >>>>>> *Romain Manni-Bucau*
> >>>>>> *Twitter: @rmannibucau <https://twitter.com/rmannibucau>*
> >>>>>> *Blog: **http://rmannibucau.wordpress.com/*<
> >>>>> http://rmannibucau.wordpress.com/>
> >>>>>> *LinkedIn: **http://fr.linkedin.com/in/rmannibucau*
> >>>>>> *Github: https://github.com/rmannibucau*
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>> 2013/2/6 Chet Hosey <[email protected]>
> >>>>>>
> >>>>>>>
> >>>>>>> That was my expectation too. But it just isn't working that way for
> >> me
> >>>>>>> with AJP.
> >>>>>>>
> >>>>>>> Apache httpd is listening on port 8888 and forwarding application
> >>>>> requests
> >>>>>>> (/rs-test/*) to TomEE via AJP. TomEE is listening on ports 8080 for
> >>>>> HTTP
> >>>>>>> and 8009 for AJP requests. If the UriInfo matched the request info,
> >>>>> then
> >>>>>>> the port number given should be 8080 when loading an app from TomEE
> >>>>>>> directly, and 8888 when using httpd to load the app via AJP.
> >>>>>>>
> >>>>>>> When I request http://servername:8080/rs-**test/<
> >>>>> http://servername:8080/rs-test/>to get content directly from TomEE
> via
> >>>>> HTTP, the UriInfo methods match the
> >>>>>>> request info, which also matches the server.xml host name and HTTP
> >>>>>>> connector port (8080). But when I request
> >> http://servername:8888/rs-**
> >>>>>>> test/ <http://servername:8888/rs-test/> to get content from TomEE
> >> over
> >>>>>>> AJP, UriInfo still lists the HTTP connector port (8080) instead of
> >> the
> >>>>>>> request port (8888). The HttpServletRequest and HttpHeaders objects
> >> do
> >>>>>>> return the request port, but UriInfo does not.
> >>>>>>>
> >>>>>>> What I tried:
> >>>>>>>
> >>>>>>> 1. Set up the environment
> >>>>>>>      1. export TESTDIR=/tmp/test
> >>>>>>>      2. mkdir -p $TESTDIR
> >>>>>>>      3. export JDK_HOME=/opt/java/jdk1.7.0_11
> >>>>>>>      4. export PATH=$JDK_HOME/bin:$PATH
> >>>>>>> 2. Download, build, and install Apache httpd
> >>>>>>>      1. Download and unpack httpd-2.2.23.tar.bz2
> >>>>>>>      2. cd httpd-2.2.23
> >>>>>>>      3. ./configure --prefix=$TESTDIR/httpd
> >>>>>>>      4. make && make install
> >>>>>>> 3. Download, build, and install mod_jk
> >>>>>>>      1. Download and unpack tomcat-connectors-1.2.37-src.**tar.gz
> >>>>>>>      2. cd tomcat-connectors-1.2.37-src/**native
> >>>>>>>      3. ./configure --with-apxs=$TESTDIR/httpd/**bin/apxs
> >>>>>>>      4. make && cp apache-2.0/mod_jk.so $TESTDIR/httpd/modules/
> >>>>>>> 4. Download and unpack apache-tomee-1.5.1-jaxrs.tar.**gz
> >>>>>>> 5. Configure Apache httpd
> >>>>>>>      1. Edit $TESTDIR/httpd/conf/httpd.conf
> >>>>>>>            1. Change Listen setting to port 8888 on public IP
> >>>>>>>            2. Append the following to load and configure mod_jk:
> >>>>>>>
> >>>>>>>         LoadModule jk_module modules/mod_jk.so
> >>>>>>>         JkWorkersFile $TESTDIR/httpd/conf/workers.**properties
> >>>>>>>         JkShmFile $TESTDIR/httpd/logs/mod_jk.shm
> >>>>>>>         JkLogFile $TESTDIR/httpd/logs/mod_jk.log
> >>>>>>>         JkLogLevel info
> >>>>>>>         JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
> >>>>>>>         JkMount /rs-test/* worker1
> >>>>>>>
> >>>>>>>      2. Create $TESTDIR/httpd/conf/workers.**properties with the
> >>>>>>>         following content:
> >>>>>>>
> >>>>>>>         worker.list=worker1
> >>>>>>>         worker.worker1.type=ajp13
> >>>>>>>         worker.worker1.host=localhost
> >>>>>>>         worker.worker1.port=8009
> >>>>>>>
> >>>>>>> 6. Configure TomEE and create test app
> >>>>>>>      1. Edit conf/server.xml:
> >>>>>>>            1. Add jvmRoute="worker1" to engine configuration
> >>>>>>>            2. Change Engine "defaultHost" and Host "name" values to
> >>>>>>>               external host name
> >>>>>>>      2. Create test application
> >>>>>>>            1. Create webapps/rs-test/WEB-INF/**classes/test
> >>>>> directory.
> >>>>>>>            2. Create
> >>>>> webapps/rs-test/WEB-INF/**classes/test/TestRS.java
> >>>>>>> with
> >>>>>>>               the following content:
> >>>>>>>
> >>>>>>>         package test;
> >>>>>>>         import java.net.URI;
> >>>>>>>         import javax.servlet.http.**HttpServletRequest;
> >>>>>>>         import javax.ws.rs.*;
> >>>>>>>         import javax.ws.rs.core.*;
> >>>>>>>         @Path("")
> >>>>>>>         public class TestRS {
> >>>>>>>
> >>>>>>>             @GET
> >>>>>>>             @Produces({MediaType.TEXT_**PLAIN})
> >>>>>>>             public String defaultPage(@Context UriInfo uriInfo,
> >>>>>>>                   @Context HttpHeaders hh, @Context
> >>>>>>>         HttpServletRequest httpServletRequest) {
> >>>>>>>                String response =
> >>>>>>>                   "uriInfo.getAbsolutePath(): "
> >>>>>>>                      + uriInfo.getAbsolutePath() + "\n"
> >>>>>>>                   + "uriInfo.getBaseUri(): "
> >>>>>>>                      + uriInfo.getBaseUri() + "\n"
> >>>>>>>                   + "uriInfo.getRequestUri(): "
> >>>>>>>                      + uriInfo.getRequestUri() + "\n"
> >>>>>>>                   + "httpServletRequest.**getLocalAddr(): "
> >>>>>>>                      + httpServletRequest.**getLocalAddr() + "\n"
> >>>>>>>                   + "httpServletRequest.**getLocalName(): "
> >>>>>>>                      + httpServletRequest.**getLocalName() + "\n"
> >>>>>>>                   + "httpServletRequest.**getLocalPort(): "
> >>>>>>>                      + httpServletRequest.**getLocalPort() + "\n"
> >>>>>>>                   + "httpServletRequest.**getServerName(): "
> >>>>>>>                      + httpServletRequest.**getServerName() + "\n"
> >>>>>>>                   + "httpServletRequest.**getServerPort(): "
> >>>>>>>                      + httpServletRequest.**getServerPort() +
> >> "\n\n";
> >>>>>>>                for (String header :
> >>>>> hh.getRequestHeaders().keySet(**))
> >>>>>>> {
> >>>>>>>                   response += header + ":\n";
> >>>>>>>                   for (String value :
> >>>>>>>         hh.getRequestHeaders().get(**header)) {
> >>>>>>>                      response += "\t" + value + "\n";
> >>>>>>>                   }
> >>>>>>>                }
> >>>>>>>                return response;
> >>>>>>>             }
> >>>>>>>         }
> >>>>>>>
> >>>>>>>        3. Compile test class with javac -classpath
> >>>>>>>           lib/javaee-api-6.0-4-tomcat.**jar:lib/servlet-api.jar
> >>>>>>>           webapps/rs-test/WEB-INF/**classes/test/TestRS.java
> >>>>>>>
> >>>>>>> 7. Start services
> >>>>>>>      1. Run apache-tomee-jaxrs-1.5.1/bin/**startup.sh to start
> TomEE
> >>>>>>>      2. Run httpd/bin/apachectl start to start httpd.
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>> On Wed, Feb 6, 2013 at 1:17 AM, Romain Manni-Bucau <
> >>>>> [email protected]<mailto:
> >>>>>>> [email protected]>**> wrote:
> >>>>>>>
> >>>>>>> UriInfo matches the http request info...
> >>>>>>> Le 6 févr. 2013 07:16, "Chet Hosey" <[email protected]
> >>>>>>> <mailto:[email protected]>> a écrit :
> >>>>>>>
> >>>>>>>
> >>>>>>>> After building httpd 2.2.23 and mod_jk 1.2.37, I configured an
> >>>>>>> AJP proxy
> >>>>>>>> for the TomEE test instance and set the jvmRoute in server.xml to
> >>>>>>> match the
> >>>>>>>> worker name from workers.properties.
> >>>>>>>>
> >>>>>>>> A request through httpd shows httpd's port number for the
> >>>>>>>> httpServletRequest methods, but still shows the TomEE HTTP
> >>>>>>> connector port
> >>>>>>>> in the URIs returned by the uriInfo methods.
> >>>>>>>>
> >>>>>>>> Doing string replacements seems fairly inelegant but I suppose
> >>>>>>> it's an
> >>>>>>>> option for custom apps. It would be surprising to learn that the
> >>>>>>> only other
> >>>>>>>> option is to configure the TomEE instances' HTTP connectors on
> >>>>>>> the same
> >>>>>>>> port as the httpd server, since each TomEE instance would then
> need
> >> a
> >>>>>>>> dedicated IP.
> >>>>>>>>
> >>>>>>>> I've filed TOMEE-757 in JIRA, as it's hard to imagine that this
> >>>>>>> behavior is
> >>>>>>>> intended.
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> On Tue, Feb 5, 2013 at 9:17 AM, Chet Hosey <[email protected]
> >>>>>>> <mailto:[email protected]>> wrote:
> >>>>>>>>
> >>>>>>>>> Ahh, that's a good thought. It was the default value of
> >>>>>>> "localhost".
> >>>>>>>> After
> >>>>>>>>> changing the "name" attribute on the Host entry and updating the
> >>>>>>>>> defaultHost on the Engine, I'm getting the expected host name
> >>>>>>> in the
> >>>>>>>>> response.
> >>>>>>>>>
> >>>>>>>>> This leads me to wonder what happens when using AJP. I'm
> >>>>>>> picturing a
> >>>>>>>> setup
> >>>>>>>>> where httpd runs on port 80 and proxies to multiple TomEE
> >>>>>>> instances via
> >>>>>>>>> AJP. If the HTTP connector port is still used by the UriInfo
> >>>>>>> methods,
> >>>>>>>> then
> >>>>>>>>> TomEE would require special access (root or authbind) to bind
> >>>>>>> to port 80
> >>>>>>>> to
> >>>>>>>>> work around this behavior. And it wouldn't be possible to run
> >>>>>>> multiple
> >>>>>>>>> TomEE instances on the same IP, since they'd all have to bind
> >>>>>>> to port 80
> >>>>>>>> to
> >>>>>>>>> ensure URI correctness.
> >>>>>>>>>
> >>>>>>>>> I'll have to experiment to find out. If I get the chance to do
> >>>>>>> so, I'll
> >>>>>>>>> report results back.
> >>>>>>>>>
> >>>>>>>>> Thanks!
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>> On Tue, Feb 5, 2013 at 1:16 AM, Romain Manni-Bucau <
> >>>>>>>> [email protected] <mailto:[email protected]>**>wrote:
> >>>>>>>
> >>>>>>>>>
> >>>>>>>>>> Hi,
> >>>>>>>>>>
> >>>>>>>>>> What's your host in the server.xml?
> >>>>>>>>>> Le 5 févr. 2013 06:30, "Chet Hosey" <[email protected]
> >>>>>>> <mailto:[email protected]>> a écrit :
> >>>>>>>
> >>>>>>>>>>
> >>>>>>>>>>> I've been using apache-tomee-1.5.1-jaxrs as a platform for
> >>>>>>> learning
> >>>>>>>>>> JAX-RS
> >>>>>>>>>>> and have run into some confusion about UriInfo determines
> >>>>>>> the base
> >>>>>>>> URI.
> >>>>>>>>>> In
> >>>>>>>>>>> my testing the URIs returned by UriInfo include the correct
> port
> >>>>>>>> number.
> >>>>>>>>>>> But the host name is always "localhost", even when I'm
> >>>>>>> accessing TomEE
> >>>>>>>>>> from
> >>>>>>>>>>> a remote machine.
> >>>>>>>>>>>
> >>>>>>>>>>> It's possible that UriInfo is meant to build identifiers,
> >>>>>>> and not
> >>>>>>>>>> locators.
> >>>>>>>>>>> This would explain why it's not called UrlInfo. But the
> >>>>>>> design of
> >>>>>>>>>>> UriBuilder suggests that one should be able to call
> >>>>>>>>>>>
> >>>>>>>>>>> uriInfo.getBaseUriBuilder()
> >>>>>>>>>>>       .path(User.class, "getUserInfo")
> >>>>>>>>>>>       .path(userId).build();
> >>>>>>>>>>>
> >>>>>>>>>>> and use the result as a hyperlink in a JAX-RS response.
> >>>>>>>>>>>
> >>>>>>>>>>> Having used mod_jk with JBoss, I know that it can override
> >>>>>>> the values
> >>>>>>>>>>> returned by HttpServletRequest methods with parameters like
> >>>>>>>>>> JK_LOCAL_NAME.
> >>>>>>>>>>> But since this is just a sandbox I'm accessing Tomcat directly,
> >>>>>>>> without
> >>>>>>>>>> an
> >>>>>>>>>>> Apache httpd proxy. But this led me to wonder what
> >>>>>>>>>>> httpServletRequest.**getlocalName() would return. So I created
> >>>>>>> a test
> >>>>>>>>>> method
> >>>>>>>>>>> to find out, using the following signature:
> >>>>>>>>>>>
> >>>>>>>>>>> @GET
> >>>>>>>>>>> @Produces({MediaType.TEXT_**PLAIN})
> >>>>>>>>>>> public String defaultPage(@Context UriInfo uriInfo,
> >>>>>>>>>>>       @Context HttpHeaders hh,
> >>>>>>>>>>>       @Context HttpServletRequest httpServletRequest) {
> >>>>>>>>>>>
> >>>>>>>>>>> The output surprised me. The HttpServletRequest methods use the
> >>>>>>>> correct
> >>>>>>>>>>> host name and IP address, and the "Host" header uses the public
> >>>>>>>> address.
> >>>>>>>>>>> The UriInfo methods get the port correct, but they still use
> >>>>>>>>>> "localhost" as
> >>>>>>>>>>> the host name.
> >>>>>>>>>>>
> >>>>>>>>>>> uriInfo.getAbsolutePath():
> >>>>>>>>>>> http://localhost:8081/sample-**app-1.0-SNAPSHOT/<
> >>>>> http://localhost:8081/sample-app-1.0-SNAPSHOT/>
> >>>>>>>>>>> uriInfo.getBaseUri():
> >>>>>>>> http://localhost:8081/sample-**app-1.0-SNAPSHOT<
> >>>>> http://localhost:8081/sample-app-1.0-SNAPSHOT>
> >>>>>>>>>>> uriInfo.getRequestUri():
> >>>>>>>>>> http://localhost:8081/sample-**app-1.0-SNAPSHOT/<
> >>>>> http://localhost:8081/sample-app-1.0-SNAPSHOT/>
> >>>>>>>>>>> httpServletRequest.**getLocalAddr(): 1.2.3.4
> >>>>>>>>>>> httpServletRequest.**getLocalName(): www.example.com
> >>>>>>> <http://www.example.com>
> >>>>>>>>>>> httpServletRequest.**getLocalPort(): 8081
> >>>>>>>>>>> httpServletRequest.**getServerName(): www.example.com
> >>>>>>> <http://www.example.com>
> >>>>>>>>>>> httpServletRequest.**getServerPort(): 8081
> >>>>>>>>>>>
> >>>>>>>>>>> host:
> >>>>>>>>>>> www.example.com:8081 <http://www.example.com:8081>
> >>>>>>>
> >>>>>>>>>>>
> >>>>>>>>>>> Is there a way to use TomEE's embedded CXF REST
> >>>>>>> implementation to
> >>>>>>>>>> generate
> >>>>>>>>>>> URIs that can be used by external clients to locate other
> >>>>>>> resources
> >>>>>>>>>> within
> >>>>>>>>>>> the same application? Or am I making bad assumptions about
> >>>>>>> the purpose
> >>>>>>>>>> of
> >>>>>>>>>>> the UriInfo methods that return UriBuilders?
> >>>>>>>>>>>
> >>>>>>>>>>> -- Chet
> >>>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>
> >>>>>
> >>
> >>
>
>

Reply via email to