Proxy Target

classic Classic list List threaded Threaded
13 messages Options
nicholas nicholas
Reply | Threaded
Open this post in threaded view
|

Proxy Target

Hello; I am trying to use the proxy target option as outlined in the Features section. My request looks more or less like this:
{
    "type":"READ"
    "mbean":"jboss:service=Naming",
    "attribute":"Port",
    "target": { 
                "url":"service:jmx:rmi:///jndi/rmi://jboss-as:8686/jmxrmi",
                "password":"admin",
                "user":"s!cr!t"
              },
  }
but I always get an error saying the MBean is not registered, so I do not believe Jolokia is relaying my request as I expected. Is this feature implemented ? Cheers. //Nicholas
roland roland
Reply | Threaded
Open this post in threaded view
|

Re: Proxy Target

nicholas wrote
Is this feature implemented ?
Yes, of course ;-)

Which agent at which version are you using for the proxy ? How do you access the agent ? (with a client library or directly ?). Can you please post the error response ?

thanx ....
... roland
... roland
Nicholas Nicholas
Reply | Threaded
Open this post in threaded view
|

Re: Proxy Target

Right, sorry.... I think I broke 8 of the 10 rules on posting good questions :)

I am using the 0.83 war agent. All my other [direct] requests  work ok. To elaborate a little bit, I am using a custom JMX Remoting ClientProvider that delegates all MBeanServerConnection requests to a pool of *actual* remote connections. The code for this client provider is here:  https://svn.java.net/svn/helios~svn/helios/trunk/helios-collectors/collectors-jmx-proxies/src/main/java/org/helios/collectors/jmxproxies/protocol/hsp. My tests using this ClientProvider are successful in other scenarios so I am fairly sure it is not an issue there, and the error messages (and debugging) indicate that the ClientProvider is not actually being called.

The HSP protocol defines a URL which is hsp://[host]/[vm]/[default domain] and it internally finds an MBean instance using those options where the pool of "actual" connections reside.

The simplest client side code to reproduce this is:

var jboss = {
    type:"read",
    mbean:"jboss:service=Naming",
    attribute:"Port",
    target: { url:"service:jmx:hsp://njw810/default/jboss?shared=true" }
  };
var jolokia = new Jolokia({url: "/jolokia"});
jolokia.request(jboss);

In this example, the jolokia client  instance works fine for "non-target" calls. The error message on the server is as follows:

2011-03-16 07:34:51.738:INFO:/jolokia:jolokia-agent: URI: /jolokia/read/jboss:service=Naming/Port null null
2011-03-16 07:34:51.738:INFO:/jolokia:jolokia-agent: Path-Info: /read/jboss:service=Naming/Port null null
2011-03-16 07:34:51.738:INFO:/jolokia:jolokia-agent: Request: JmxRequest[READ mbean=jboss:service=Naming, attribute=Port] null null
2011-03-16 07:34:51.738:WARN:/jolokia:jolokia-agent: Error 404
javax.management.InstanceNotFoundException: jboss:service=Naming
        at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1094)
        at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:662)
        at com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:638)
        at org.jolokia.handler.ReadHandler.doHandleRequest(ReadHandler.java:70)
        at org.jolokia.handler.JsonRequestHandler.handleRequest(JsonRequestHandler.java:83)
        at org.jolokia.backend.MBeanServerHandler.handleRequest(MBeanServerHandler.java:108)
        at org.jolokia.backend.MBeanServerHandler.dispatchRequest(MBeanServerHandler.java:98)
        at org.jolokia.backend.LocalRequestDispatcher.dispatchRequest(LocalRequestDispatcher.java:85)
        at org.jolokia.backend.BackendManager.callRequestDispatcher(BackendManager.java:181)
        at org.jolokia.backend.BackendManager.handleRequest(BackendManager.java:160)
        at org.jolokia.http.HttpRequestHandler.executeRequest(HttpRequestHandler.java:146)
        at org.jolokia.http.HttpRequestHandler.handleGetRequest(HttpRequestHandler.java:77)
        at org.jolokia.http.AgentServlet$2.handleRequest(AgentServlet.java:151)
        at org.jolokia.http.AgentServlet.handle(AgentServlet.java:112)
        at org.jolokia.http.AgentServlet.doGet(AgentServlet.java:95)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
        at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:527)
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:423)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:493)
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:225)
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:930)
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:358)
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:183)
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:866)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
        at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:245)
        at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:113)
        at org.eclipse.jetty.server.Server.handle(Server.java:351)
        at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:594)
        at org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:1042)
        at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:549)
        at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:211)
        at org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:424)
        at org.eclipse.jetty.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:506)
        at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:436)
        at java.lang.Thread.run(Thread.java:662)
2011-03-16 07:34:51.766:INFO:/jolokia:jolokia-agent: Response: {"error_type":"javax.management.InstanceNotFoundException","error":"javax.management.InstanceNotFoundException : jboss:service=Naming","status":404,"stacktrace":"javax.management.InstanceNotFoundException: jboss:service=Naming\n\tat com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1094)\n\tat com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:662)\n\tat com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:638)\n\tat org.jolokia.handler.ReadHandler.doHandleRequest(ReadHandler.java:70)\n\tat org.jolokia.handler.JsonRequestHandler.handleRequest(JsonRequestHandler.java:83)\n\tat org.jolokia.backend.MBeanServerHandler.handleRequest(MBeanServerHandler.java:108)\n\tat org.jolokia.backend.MBeanServerHandler.dispatchRequest(MBeanServerHandler.java:98)\n\tat org.jolokia.backend.LocalRequestDispatcher.dispatchRequest(LocalRequestDispatcher.java:85)\n\tat org.jolokia.backend.BackendManager.callRequestDispatcher(BackendManager.java:181)\n\tat org.jolokia.backend.BackendManager.handleRequest(BackendManager.java:160)\n\tat org.jolokia.http.HttpRequestHandler.executeRequest(HttpRequestHandler.java:146)\n\tat org.jolokia.http.HttpRequestHandler.handleGetRequest(HttpRequestHandler.java:77)\n\tat org.jolokia.http.AgentServlet$2.handleRequest(AgentServlet.java:151)\n\tat org.jolokia.http.AgentServlet.handle(AgentServlet.java:112)\n\tat org.jolokia.http.AgentServlet.doGet(AgentServlet.java:95)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:707)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:820)\n\tat org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:527)\n\tat org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:423)\n\tat org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)\n\tat org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:493)\n\tat org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:225)\n\tat org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:930)\n\tat org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:358)\n\tat org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:183)\n\tat org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:866)\n\tat org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)\n\tat org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:245)\n\tat org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)\n\tat org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:113)\n\tat org.eclipse.jetty.server.Server.handle(Server.java:351)\n\tat org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:594)\n\tat org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:1042)\n\tat org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:549)\n\tat org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:211)\n\tat org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:424)\n\tat org.eclipse.jetty.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:506)\n\tat org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:436)\n\tat java.lang.Thread.run(Thread.java:662)\n"} null null

===

The client side error message does not add any additional information, but I did observe that FireBug reports an HTTP GET of http://localhost:8161/jolokia/read/jboss:service=Naming/Port  so it would seem the client is not including the target.


The Jetty instance is 7.1.6. The platform is Ubuntu 10.10 64. The JVM is java-sun 1.6.0_24.

Based on the request logged in the server message, it seems my attempt to specify a target is being ignored, so perhaps the JSON structure of my target is defective.

Thanks for looking at this.

//Nicholas

roland roland
Reply | Threaded
Open this post in threaded view
|

Re: Proxy Target

Hi Nicholas,

the point here is, that you need to use a POST request in order to provide the proxy information, the server log indicates a GET request, though. This is obviously a deficit in the Jolokia Javascript library, I'm going to fix this for the next release. Jolokia will then switch automatically to POST if a target proxy configuration is given.

In the meantime, you can force to use POST requests by providing an extra option, either when sending the request or when creating the Jolokia object:

var jolokia = new Jolokia({url: "/jolokia", method: "post"}); 

See also http://www.jolokia.org/reference/html/clients.html#js-request-options-table for more available options.

BTW, thanks for this pointer to a JSR-160 pools. Something similar is on the list for the Jolokia JSR-160 proxy, too in order to support JSR-160 connection pooling directly. The lifecycle of the pool will be a bit tricky, though.

bye and thanks for spotting this issue ...

... roland
nicholas nicholas
Reply | Threaded
Open this post in threaded view
|

Re: Proxy Target

In reply to this post by Nicholas
A bit more information:

I am using jQuery 1.4.4.
I also tried doing a direct post using jQuery Ajax and I got a different result. In this case, I am attempting to implement a simple non-target example, but the server only interprets the request as a "version":

$.post('/jolokia', {"type":"read", "mbean":"java.lang:type=Threading", "attribute":"ThreadCount" },        
    function(data) {
        console.log(data);
    }
);



I also used:

$.ajax({
  type: 'POST',
  url: "/jolokia",
  data: {"type":"read", "mbean":"java.lang:type=Threading", "attribute":"ThreadCount" },
  success: function(data) { console.log(data); },
  dataType: "json"
});



From Firebug:

The actual post is:
URL: http://localhost:8161/jolokia/
Parameters:
   attribute: ThreadCount
   mbean: java.lang:type=Threading
   type: read
Source: type=read&mbean=java.lang%3Atype%3DThreading&attribute=ThreadCount

The response is:

{"timestamp":1300283068,"status":200,"request":{"type":"version"},"value":{"protocol":"4.1","agent":"0.83","info":{"product":"jetty","vendor":"Eclipse","version":"7.1.6.v20100715"}}}



Screen Shot From Firebug
nicholas nicholas
Reply | Threaded
Open this post in threaded view
|

Re: Proxy Target

In reply to this post by roland
Missed your post before my last reply.
I will try this now.
nicholas nicholas
Reply | Threaded
Open this post in threaded view
|

Re: Proxy Target

In reply to this post by roland
Still have the same issue as the straight Ajax posts. My client side code is:

var req = {
    "type":"read",
    "mbean":"java.lang:type=Threading",
    "attribute":"ThreadCount"
  };
var jolokia = new Jolokia({url: "/jolokia", method: "post"});
jolokia.request(req);

The Firebug rendering of the request:

Firebug Rendering of Post Request

The Firebug rendering of the response:

The Firebug rendering of the post response
roland roland
Reply | Threaded
Open this post in threaded view
|

Re: Proxy Target

In reply to this post by nicholas
The point is, that when you use $.post() the data is send form-urlencoded but the agent expects a plain JSON object in the InputStream. So to make the request work with jQuery you should use the jQuery option processData: false, too.

Just out of curiosity: Is there a particular reason why you are not using the Jolokia Javascript library (which take all these already into account) ?

... roland
roland roland
Reply | Threaded
Open this post in threaded view
|

Re: Proxy Target

In reply to this post by nicholas
That's indeed strange, that using post with the Jolokia API still seems to trigger the version command, and not the 'read' command. BTW, there is a QUnit Testsuite with ~ 120 tests at https://github.com/rhuss/jolokia/blob/master/client/javascript/test-app/src/main/webapp/jolokia-all-test.html which tests for POST requests as well.

I will try to verify this issue now.

... roland
nicholas nicholas
Reply | Threaded
Open this post in threaded view
|

Re: Proxy Target

In reply to this post by roland
Added the processData: "false", but got the same result (the agent info).

Request:

$.ajax({
  processData: "false",
  type: 'POST',
  url: "/jolokia",
  data: {"type":"read", "mbean":"java.lang:type=Threading", "attribute":"ThreadCount" },
  success: function(data) { console.log(data); },
  dataType: "json"
});



Response:

{"timestamp":1300284680,"status":200,"request":{"type":"version"},"value":{"protocol":"4.1","agent":"0.83","info":{"product":"jetty","vendor":"Eclipse","version":"7.1.6.v20100715"}}}


My preference is to use the jolokia javascript client. I was just trying out different things trying to capture more information.
roland roland
Reply | Threaded
Open this post in threaded view
|

Re: Proxy Target

In reply to this post by roland
Uff, this one took me some time. I debugged everything and it seems, that the POST send from Javascript (aka $.ajax() aka xhdr.send()) results on the serverside in an GET request, which then of course don't know about any content and hence returns the version as a default.

After looking at ticket https://bugs.eclipse.org/bugs/show_bug.cgi?id=331194, the reason seems evident:

The issue here is that jetty is doing a redirect from /test to /test/, and a
redirected POST will end up as a GET.


The reason for the redirect is that the servlet spec treats the root of a
context like a directory and there is no valid set of contextPath + servletPath
+ pathInfo that is legal for a URL of /test to a context /test

More importantly, if you send back HTML from a request to /test then any
relative links will be relative to / instead of /test.   Thus the redirect to
/test/ fixes this.
So, the simple fix in order to avoid the redirect is, to use /jolokia/ 
as agent URL (not "/jolokia") !

This is BTW only necessary, if you deploy the agent separately
for the Javascript on the same server, otherwise, if they live under the same
webapp-context (but with a different servlet mapping), the issue should not occur here.
... roland
nicholas nicholas
Reply | Threaded
Open this post in threaded view
|

Re: Proxy Target

Ah crap. I'm really sorry. What a silly waste of time !

Anyways, this now works:

var jboss = {
    type:"read",
    mbean:"jboss:service=Naming",
    attribute:"Port",
    target: { url:"service:jmx:hsp://njw810/default/jboss?shared=true" }
  };

var jolokia = new Jolokia({url: "/jolokia/", method: "post"});
jolokia.request(jboss);


Response:

{"timestamp":1300297368,"status":200,"request":{"mbean":"jboss:service=Naming","target":{"url":"service:jmx:hsp:\/\/njw810\/default\/jboss?shared=true"},"attribute":"Port","type":"read"},"value":"1099"}

Thanks a lot Roland !

//Nicholas
roland roland
Reply | Threaded
Open this post in threaded view
|

Re: Proxy Target

nicholas wrote
Ah crap. I'm really sorry. What a silly waste of time !
No problem. I just extended jolokia.js to add a trailing slash
transparently for POST requests if missing. So, this particular
issue should be banned for now ;-)

bye ...
... roland