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