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 > >>>>>>>>>>> > >>>>>>>>>> > >>>>>>>>> > >>>>>>>>> > >>>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>> > >>>>> > >> > >> > >
