Artemis jolokia rest api returns no real data (Jsr160ProxyNotEnabledByDefaultAnymoreDispatcher) - activemq-artemis

I've an Artemis Broker (2.17) running on my dev machine for local testing.
From the web-console I've extractet the request to get the names of all queues.
When I execute the request from the browser console i get a JSON result like this:
{
"request": {
"mbean": "org.apache.activemq.artemis:broker=\"MyBroker\"",
"arguments": [
"ANYCAST"
],
"type": "exec",
"operation": "getQueueNames(java.lang.String)"
},
"value": [
"DLQ",
"ExpiryQueue"
],
"timestamp": 1624274952,
"status": 200
}
When I execute the same request from my code I get a very different result:
{
"request": {
"type": "version"
},
"value": {
"agent": "1.6.2",
"protocol": "7.2",
"config": {
"listenForHttpService": "true",
"authIgnoreCerts": "false",
"agentId": "192.168.1.41-30064-15b82644-servlet",
"debug": "false",
"agentType": "servlet",
"policyLocation": "file:/C:/Artemis/MyBroker/etc//jolokia-access.xml",
"agentContext": "/jolokia",
"serializeException": "false",
"mimeType": "text/plain",
"dispatcherClasses": "org.jolokia.http.Jsr160ProxyNotEnabledByDefaultAnymoreDispatcher",
"authMode": "basic",
"authMatch": "any",
"streaming": "true",
"canonicalNaming": "true",
"historyMaxEntries": "10",
"allowErrorDetails": "false",
"allowDnsReverseLookup": "true",
"realm": "jolokia",
"includeStackTrace": "false",
"mbeanQualifier": "qualifier=hawtio",
"useRestrictorService": "false",
"debugMaxEntries": "100"
},
"info": {
"product": "jetty",
"vendor": "Eclipse",
"version": "9.4.27.v20200227"
}
},
"timestamp": 1624274809,
"status": 200
}
Jsr160ProxyNotEnabledByDefaultAnymoreDispatcher seams very strange. But when searching for this name I couldn't realy find anything usefull. Also I cannot find any usefull information in the Artemis logs.
Here is my code:
using System;
using System.Net.Http;
using System.Text;
using System.Threading;
const String username = "admin";
const String password = "password";
var encoded = Convert.ToBase64String( Encoding.GetEncoding( "ISO-8859-1" )
.GetBytes( username + ":" + password ) );
var url = "http://localhost:8161/console/jolokia/?maxDepth=7&maxCollectionSize=50000&ignoreErrors=true&canonicalNaming=false";
var http = new HttpClient();
http.BaseAddress = new("http://localhost:8161/");
http.DefaultRequestHeaders.Add( "Authorization", "Basic " + encoded );
http.DefaultRequestHeaders.Add( "Origin", "http://localhost:8161/" );
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new(url),
Content = new StringContent( "{\"type\":\"exec\",\"mbean\":\"org.apache.activemq.artemis:broker=\\\"MyBroker\\\"\",\"operation\":\"getQueueNames(java.lang.String)\",\"arguments\":[\"ANYCAST\"]}" )
};
request.Content.Headers.ContentType = new("text/json");
var response = await http.SendAsync( request, HttpCompletionOption.ResponseHeadersRead, CancellationToken.None );
if ( response.IsSuccessStatusCode )
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine( content );
}
else
Console.WriteLine( "Request failed...." );
Console.ReadLine();
In the bootstrap.xml the binding is set to 0.0.0.0 which should be ok.
jolokia-access.xml contained <allow-origin>*://localhost*</allow-origin> which should be fine but just to be sure I've replaced it with <allow-origin>*</allow-origin>
Is there something I need to configure to make this work?

Jolokia requests can be sent in two ways: Either as a HTTP GET request, in which case the request parameters are encoded completely in the URL. Or as a POST request where the request is put into a JSON payload in the HTTP request's body. See the Jolokia Protocol for further details.
When the Jolokia service doesn't get any request it will answer with service information, ie:
{
"request": {
"type": "version"
},
"value": {
...
To request the queue names using an HTTP GET request
curl -H "Origin:http://localhost:8161" -u admin:admin http://localhost:8161/console/jolokia/exec/org.apache.activemq.artemis:broker=\"MyBroker\"/getQueueNames/ANYCAST
To request the queue names using an HTTP POST request
curl -X POST -H "Content-Type: application/json" -H "Origin:http://localhost:8161" -u admin:admin http://localhost:8161/console/jolokia -d '{"type" : "EXEC", "mbean" : "org.apache.activemq.artemis:broker=\"MyBroker\"", "operation" : "getQueueNames", "arguments" : ["ANYCAST"]}'

Your code is using an HTTP GET, but it is using a fixed URL (i.e. http://localhost:8161/console/jolokia/?maxDepth=7&maxCollectionSize=50000&ignoreErrors=true&canonicalNaming=false and a payload (i.e. {"type":"exec","mbean":"org.apache.activemq.artemis:broker="MyBroker","operation":"getQueueNames(java.lang.String)","arguments":["ANYCAST"]}"). This does not conform with the Jolokia protocol.
If you use an HTTP GET then everything should be in the URL itself presumably just like it was your browser console. For example, use this:
http://localhost:8161/console/jolokia/exec/org.apache.activemq.artemis:broker="MyBroker"/getQueueNames/ANYCAST

Related

Wiremock not able to match the url

I have very basic mapping.json
{
"mappings": [
{
"priority": 1,
"request": {
"method": "GET",
"url": "/your/url?and=query"
},
"response": {
"status": 200,
"statusMessage": "query param test"
}
},
{
"priority": 2,
"request": {
"method": "GET",
"url": "/your"
},
"response": {
"status": 200,
"statusMessage": "no query param"
}
}
]
}
It's the exact same example as given in the documentation.
Result:
admin ~ % curl -i http://localhost:8081/your
HTTP/1.1 200 no query param
Matched-Stub-Id: 6ff84303-8abb-48d0-bd27-679de118afc7
Transfer-Encoding: chunked
Server: Jetty(9.2.z-SNAPSHOT)
admin ~ % curl -i http://localhost:8081/your/url?and=query
zsh: no matches found: http://localhost:8081/your/url?and=query
admin ~ %
Cannot figure out what I am doing wrong here. It's exactly the same example give in the documentation. I tried putting query parameter like this:
"queryParameters" : {
"search_term" : {
"equalTo" : "WireMock"
}
},
This also didn't help.
TIA
Check out the answer and comment from this question, but the tl;dr is that if you want to include query parameters in a CURL request, you have to have the URL in quotes.
That would explain why Postman worked, and the CURL request without query parameters also worked, but the CURL request with query parameters did not.
curl -i 'http://localhost:8081/your/url?and=query' should be enough to solve your problem (might need double quotes instead of single?)

get a particular object from jsonBody with query param of request url in wiremock

What should be the mapping object if
1) I need to pass my query
2) the query should be used to send one object out of an array of objects
curl -X POST --data '
{ "request":
{ "url": "/jsons?id=someID", "method": "GET" },
"response":
{ "status": 200, "jsonBody": {"objs":[{"id":"1","name":"abc"},{"id":"2","name":"cde"
{"id":"someID","name":"efg"}]}}}
'http://localhost:8080/__admin/mappings/new
I want the above url to return just {"id":"someID","name":"efg"}
How should i change the above mapping to get the desired output
The response should have one object for that particular get request with query param and not array of objects.
For your example it should be something like this
curl -X POST --data '
{ "request":
{ "url": "/jsons?id=someID", "method": "GET" },
"response":
{ "status": 200, "jsonBody": {"objs": {"id":"someID","name":"efg"}}}}
'http://localhost:8080/__admin/mappings/new

WireMock not mapping request by body contains

My http request send to this: https://myhost.com/ap
My http request with body :
{
"Body": {
"CommandName": "GetApplicationProfile"
},
"Header": {
"Command": "GetApplicationProfile",
}
}
I want to mapping this request by WireMock.
Here WireMock's mapping file.
{
"request": {
"url": "/my_host/ap",
"bodyPatterns": [
{
"contains": "GetApplicationProfile"
}
]
},
"response": {
"headers": {
"Content-Type": "application/json"
},
"status": 200,
"bodyFileName": "get_profile.json"
}
}
I start wireMock like this:
java -jar wiremock-standalone-2.18.0.jar --port 8080 --enable-browser-proxying -verbose
But when request was started the WireMock not map this request. Nothing happened.
why?
The problem you're having is that you shouldn't have the hostname in the url part. This is not needed. Your example message can be sent and will be matched using the following rule.
{
"request": {
"url": "/app",
"bodyPatterns": [
{
"contains": "GetApplicationProfile"
}
]
},
"response": {
"headers": {
"Content-Type": "application/json"
},
"status": 200,
"body": "ddd"
}
}
The URL should not contain the host name. It should only contain the resource path.
The url format should start with "/" e.g. /https://myhost.com/ap.
Now if u r trying this on localhost then the URL should be localhost:<port>/https://myhost.com/ap.
The file should be present at src/test/resources/__files
If not it will give error file not present.
I see 2 issues here:
1. you need to remove the host name from the url in the mapping file.
2. your request is HTTPS which means you need to start your wiremock port with https: --https-port 8080 or you change your request to HTTP

Wiremock - How can I apply response templating to the header name?

I am trying to provide a MOCK service that takes a headerName and value from the query and returns it as a (dynamic) header with the response. I am using the following response definition:
"response" : {
"status" : 200,
"statusMessage": "OK",
"headers" : {
"Content-Type" : "application/json",
"{{request.query.debugHeader}}" : "{{request.query.debugHeaderValue}}"
},
"jsonBody" : {
"headerSent": "{{request.query.debugHeader}} {{request.query.debugHeaderValue}}"
},
"transformers": ["response-template"],
"base64Body" : ""
}
The header value is correctly evaluated and put into the response template, however I can't get the header name to be taken from the request.
When sending a request:
http://localhost:8090/example?debugHeader=name&debugHeaderValue=value
The result headers I get back are:
HTTP/1.1 200 OK
Content-Type: application/json
{{request.query.debugHeader}}: value
However I want {{request.query.debugHeader}} to be replaced with the actual request parameter value ("name" in the example above).
Any ideas?
Thanks in advance
Alex
This is supported in WireMock.Net.
The request which you need to specify looks like this:
{
"Guid": "90356dba-b36c-469a-a17e-669cd84f1f05",
"Priority": 0,
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "/trans",
"IgnoreCase": false
}
]
},
"Methods": [
"get"
]
},
"Response": {
"StatusCode": 200,
"BodyDestination": "SameAsSource",
"Body": "{\"msg\": \"Hello world : {{request.path}}\" }",
"UseTransformer": true,
"Headers": {
"Content-Type": "application/json",
"Transformed-Postman-Token_{{request.path}}": "token is {{request.headers.Postman-Token}}"
}
}
}
This will add the transformed header Transformed-Postman-Token_{{request.path}} in the response.
Presently this type of variability is not part of the out-of-the-box WireMock application and would have to be custom added. In the WireMock documentation the section Extending WireMock and in particular the part on Transforming Responses.

How can I use the BigQuery REST API from the command line?

Attempting to make a plain GET request to one of the BigQuery REST APIs gives an error that looks like this:
curl https://www.googleapis.com/bigquery/v2/projects/$PROJECT_ID/jobs/$JOBID
Output:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Login Required",
"locationType": "header",
"location": "Authorization",
...
What is the correct way to invoke one of the REST APIs from the command-line, such as the query or insert APIs? The API reference has a "Try this API", but the examples don't translate directly to something you can run from the command-line.
As a disclaimer, when working from the command-line, using the bq tool will usually be sufficient, or for more complex use cases, the BigQuery client libraries enable programming with BigQuery from multiple languages. It can still be useful sometimes to make plain requests to the REST APIs to see how certain APIs work at a low level, however.
First, make sure that you have installed the Google Cloud SDK. This should include the gcloud and bq command-line tools. If you haven't already, authorize your account by running this command from your terminal:
gcloud auth login
This should prompt you to log in and then give you an access code that you can paste into your terminal. (The exact process may change over time).
Now let's try a query using the BigQuery REST API, calling the jobs.query method. Modify this script with your own project name, which you can find from the Google Cloud Console, then paste the script into your terminal:
PROJECT="YOUR_PROJECT_NAME"
QUERY="\"SELECT 1 AS x, 'foo' AS y;\""
REQUEST="{\"kind\":\"bigquery#queryRequest\",\"useLegacySql\":false,\"query\":$QUERY}"
echo $REQUEST | \
curl -X POST -d #- -H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://www.googleapis.com/bigquery/v2/projects/$PROJECT/queries
If it worked, you should see output that looks like this:
{
"kind": "bigquery#queryResponse",
"schema": {
"fields": [
{
"name": "x",
"type": "INTEGER",
"mode": "NULLABLE"
},
{
"name": "y",
"type": "STRING",
"mode": "NULLABLE"
}
]
},
"jobReference": {
"projectId": "<your project ID>",
"jobId": "<your job ID>"
},
"totalRows": "1",
"rows": [
{
"f": [
{
"v": "1"
},
{
"v": "foo"
}
]
}
],
"totalBytesProcessed": "0",
"jobComplete": true,
"cacheHit": false
}
If you haven't set up the bq command-line tool, you can use bq init from your terminal to do so. Once you have, you can try running the same query using it:
bq query --use_legacy_sql=False "SELECT 1 AS x, 'foo' AS y;"
You can also see the REST API requests that the bq tool makes by passing the --apilog= option:
bq --apilog= query --use_legacy_sql=False "SELECT [1, 2, 3] AS x;"
Now let's try an example using the jobs.insert method instead of the query API. Run this script, replacing YOUR_PROJECT_NAME with your project name:
PROJECT="YOUR_PROJECT_NAME"
QUERY="\"SELECT 1 AS x, 'foo' AS y;\""
REQUEST="{\"configuration\":{\"query\":{\"useLegacySql\":false,\"query\":${QUERY}}}}"
echo $REQUEST | \
curl -X POST -d #- -H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://www.googleapis.com/bigquery/v2/projects/$PROJECT/jobs
Unlike the query API, which returned a response immediately, you will see a result that looks similar to this:
{
"kind": "bigquery#job",
"etag": "\"<etag string>\"",
"id": "<project name>:<job ID>",
"selfLink": "https://www.googleapis.com/bigquery/v2/projects/<project name>/jobs/<job ID>",
"jobReference": {
"projectId": "<project name>",
"jobId": "<job ID>"
},
"configuration": {
"query": {
"query": "SELECT 1 AS x, 'foo' AS y;",
"destinationTable": {
"projectId": "<project name>",
"datasetId": "<anonymous dataset>",
"tableId": "<anonymous table>"
},
"createDisposition": "CREATE_IF_NEEDED",
"writeDisposition": "WRITE_TRUNCATE",
"useLegacySql": false
}
},
"status": {
"state": "RUNNING"
},
"statistics": {
"creationTime": "<timestamp millis>",
"startTime": "<timestamp millis>"
},
"user_email": "<your email address>"
}
Notice the status:
"status": {
"state": "RUNNING"
},
If you want to check on the job now, you can use the jobs.get method. Similar to before, run this from your terminal, using the job ID from the output in the previous step:
PROJECT="YOUR_PROJECT_NAME"
JOB_ID="YOUR_JOB_ID"
curl -H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://www.googleapis.com/bigquery/v2/projects/$PROJECT/jobs/$JOB_ID
If the query is done, you'll get a response that indicates as much:
...
"status": {
"state": "DONE"
},
...
Finally, we can make a request to fetch the query results, also using the REST API.
curl -H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://www.googleapis.com/bigquery/v2/projects/$PROJECT/queries/$JOB_ID
The output will look similar to when we used the jobs.query method above:
{
"kind": "bigquery#getQueryResultsResponse",
"etag": "\"<etag string>\"",
"schema": {
"fields": [
{
"name": "x",
"type": "INTEGER",
"mode": "NULLABLE"
},
{
"name": "y",
"type": "STRING",
"mode": "NULLABLE"
}
]
},
"jobReference": {
"projectId": "<project ID>",
"jobId": "<job ID>"
},
"totalRows": "1",
"rows": [
{
"f": [
{
"v": "1"
},
{
"v": "foo"
}
]
}
],
"totalBytesProcessed": "0",
"jobComplete": true,
"cacheHit": true
}