How to Extract Apache Camel URI parameters - apache-camel

Does anyone know how to extract parameter from camel URI?
I have a route defined like this
from("SOME_URI")
.to("SOME_URI")
.to("bean:myBean?method=myMethod&myParameter1=val1&myParameter2=val2")
I want to extract parameter1 and parameter2 in "myMethod" like this (I'm implementing camel in Grails)
def myMethod(def inBody, Exchange exchange){
String parameter1 = extractParameter('myParameter1')
String parameter2 = extractParameter('myParameter2')
...//rest of code
return something
}
Thank's in advance!

Main Answer
You can get what you're looking for out of the exchange:
exchange.getFromEndpoint()
Will return the Endpoint defined by "SOME_URI" and:
exchange.getFromEndpoint().getEndpointUri()
will return the String value of "SOME_URI"
Meaning your code could become:
def myMethod(def inBody, Exchange exchange){
def uri = exchange?.fromEndpoint?.endpointUri
if(uri) {
String parameter1 = extractParameter(uri, 'myParameter1')
String parameter2 = extractParameter(uri, 'myParameter2')
//...rest of code
}
return something
}
/*
* do any kind of processing you want here to manipulate the string
* and return the parameter. This code should work just fine in grails
*/
def extractParameter(String uri, String parameterName) {
def m = uri =~ "${parameterName}=([^&]+)"
return m.find() ? m[0][1] : null
}
If a Java equivalent is preferred, this should do the same:
private static String extractParameter(String uri, String parameterName) {
Matcher m = Pattern.compile(parameterName + "=([^&]+)").matcher(uri);
return m.find() ? m.group(1) : null
}
Alternative
Also note that, depending on what exactly you're trying to accomplish, a better approach might be to use the fromF DSL to supply parameters directly to your route. That way, you have the parameters available in code and you don't have to worry about extracting them, afterward.
The code snippet below is taken from the Camel Documentation of FromF.
fromF("file://%s?include=%s", path, pattern).toF("mock:%s", result);

Are val1 and val2 hardcoded values, or should they be some kind of dynamic value, maybe from the message itself?
The Camel bean component allows you to define the binding, and pass in values from the message or fixed values. See more details at: http://camel.apache.org/bean-binding.html
And you would also need to look at the number of parameters in your method signature, and the number of parameters you define in the Camel bean binding uri. They should match up.

If I understand correctly, you are trying to pass parameters into a method that is going to be invoked. The usual way to do this is to modify the Exchange object as it's flowing through the route.
from("SOME_URI")
.to("SOME_URI")
.setHeader("myParameter1", constant("val1"))
.setHeader("myParameter2", constant("val2"))
.to("bean:myBean?method=myMethod")
In your method, you just access the headers of the Exchange.
def myMethod(Exchange exchange) {
String parameter1 = exchange.getHeader("myParameter1", String.class)
String parameter2 = exchange.getHeader("myParameter2", String.class)
//...rest of code
}
Or if you want to get fancy and use Camel's bean binding,
def myMethod(Exchange exchange,
#Header("myParameter1") String parameter1,
#Header("myParameter2") String parameter2) {
//...rest of code
}
Please remember to vote up if this helps.

Related

Extract value from JMSByte message

Hi I have a consumer subscribe to a topic and receive the Byte Message.
The task i want to accomplish is to extract the value from below string i converted.
The code i used to convert Byte message is below:
if (message instanceof BytesMessage){
BytesMessage byteMessage = (BytesMessage) message;
byte[] byteData = null;
try {
byteData = new byte[(int) byteMessage.getBodyLength()];
byteMessage.readBytes(byteData);
byteMessage.reset();
}catch (JMSException e){
e.printStackTrace();
}
String stringMessage = new String(byteData);
System.out.println(stringMessage);
}
The stringMessage us show as below:
2179032 TradeId701118403 clearedTradeUsi
SW005285900447503296# clearedTradeUsiIssuer
1010051�zzz�cleared���i
i want to extract each value seperately like below. But right now i do not have any clue how to do that.. Could anyone help me with that?
TradeId: 70111840
clearedTradeUsi: SW005285900447503296
clearedTradeUsiIssuer: 1010051
As you have tagged your question with regex, I'll provide some regex solutions to find the fields.
For the trade id
TradeId\s?(\d+)
This will allow for a space to be added before the id like there is for some of the other values. The \s? matches none or one space.
For the clearedTradeUsi
clearedTradeUsi\s?(\w+)
For the clearedTradeUsiIssuer
clearedTradeUsiIssuer\s?(\d+)
Each of these regular expressions will match the respective id which will be put into group 1.

Regex to match the last value in given data

I get data from a URL, and am working on the data to check for a few conditions. The data from the URL look like this:
1528190345":100,"1528190346":100,"1528190368":100,"1528190414":100,"1528190439":99,"1528190440":99,"1528190463":100,"1528190485":100,"1528190508":100,"1528190550":100,"1528190575":100,"1528190576":100,"1528190599":100,"1528190600":100,"1528190622":100,"1528190667":100,"1528190688":100,"1528190689":100,"1528190712":100,"1528190736":100,"1528190762":100,"1528190785":100,"1528190786":100,"1528190807":100,"1528190828":100,"1528190853":100,"1528190877":100,"1528190901":100,"1528190925":100,"1528190948":100,"1528190968":100,"1528190991":100}}]
====
I have converted that too JSON
{"metric"=>"Insta_real-unique_value", "tags"=>{"host"=>"letme.quickly.com", "tier"=>"2", "device"=>"tester1", "dc"=>"xxx"}, "aggregateTags"=>["device_name", "device_ip"], "dps"=>{"1526972408"=>100, "1526972424"=>100, "1526972440"=>100, "1526972456"=>100, "1526972472"=>100, "1526972488"=>100, "1526972504"=>100, "1526972520"=>100, "1526972536"=>100, "1526972552"=>100, "1526972568"=>100, "1526972569"=>100, "1526972584"=>100, "1526972585"=>100, "1526972601"=>100, "1526972617"=>100, "1526972633"=>100, "1526972649"=>100, "1526972665"=>100, "1526972681"=>100}}
I want to extract the value that corresponds to 100. When I do this:
url = "#{URL}"
uri = URI(url)
response = Net::HTTP.get(uri)
value = response[-6..-4]
puts value
I get the last value, but when the last value changes to 99/9/0, it prints :99 or ":9.
Is there a way to get the exact value as is?
When dealing with JSON data, it's almost always better to parse the data properly rather than using regex against the string.
In this case, we can do:
JSON.parse(response)['dps'].values.last #=> 100
If the response is a json response, you must use a json parser else if is not a json response, you can use a regex expression with a Regex Object.
In case of a json response, assuming that the object is something like is declared into the variable response of the next code, you can parse it into a JObject. (using Newtonsoft.Json available from nuget repository).
See the next example :
string response = "[{\"response\":{\"1528190345\":100,\"1528190346\":100,\"1528190368\":100,\"1528190414\":100,\"1528190439\":99,\"1528190440\":99,\"1528190463\":100,\"1528190485\":100,\"1528190508\":100,\"1528190550\":100,\"1528190575\":100,\"1528190576\":100,\"1528190599\":100,\"1528190600\":100,\"1528190622\":100,\"1528190667\":100,\"1528190688\":100,\"1528190689\":100,\"1528190712\":100,\"1528190736\":100,\"1528190762\":100,\"1528190785\":100,\"1528190786\":100,\"1528190807\":100,\"1528190828\":100,\"1528190853\":100,\"1528190877\":100,\"1528190901\":100,\"1528190925\":100,\"1528190948\":100,\"1528190968\":100,\"1528190991\":100}}]";
List<Dictionary<string, Dictionary<string, int>>> values = JsonConvert.DeserializeObject<List<Dictionary<string, Dictionary<string, int>>>>(response);
Dictionary<string, Dictionary<string, int>> firstLevel = values[0]; // Access to the first object of the list closed with ']'
Dictionary<string, int> secondLevel = firstLevel["response"]; // Access to the first object response and get's it's object context of first '}' starting from the end of response
/** This is an option, if you ever knows the name of the element (1528190991) */
int thirdLevel = secondLevel["1528190991"]; // Access to the last element of the object by it's name, context of second '}' starting from the end of response.
Console.WriteLine(thirdLevel);
/** This is another option if you doesn't know the name of the element and wants ever the last element. */
List<int> listOfValues = secondLevel.Values.ToList();
Console.WriteLine(listOfValues[listOfValues.Count-1]);
Note that i've chenged a little bit your response adding [{\"response\":{\" at the start to become a json response.
If is not a json response you can use this pattern with regular expression :
:(.{2,6})}}\]$
Hope will help!

Gmail API .NET: Get full message

How do I get the full message and not just the metadata using gmail api?
I have a service account and I am able to retrieve a message but only in the metadata, raw and minimal formats. How do I retrieve the full message in the full format? The following code works fine
var request = service.Users.Messages.Get(userId, messageId);
request.Format = UsersResource.MessagesResource.GetRequest.FormatEnum.Metadata;
Message message = request.Execute();
However, when I omit the format (hence I use the default format which is FULL) or I change the format to UsersResource.MessagesResource.GetRequest.FormatEnum.Full
I get the error: Metadata scope doesn't allow format FULL
I have included the following scopes:
https://www.googleapis.com/auth/gmail.readonly,
https://www.googleapis.com/auth/gmail.metadata,
https://www.googleapis.com/auth/gmail.modify,
https://mail.google.com/
How do I get the full message?
I had to remove the scope for the metadata to be able to get the full message format.
The user from the SO post have the same error.
Try this out first.
Go to https://security.google.com/settings/security/permissions
Choose the app you are working with.
Click Remove > OK
Next time, just request exactly which permissions you need.
Another thing, try to use gmailMessage.payload.parts[0].body.dataand to decode it into readable text, do the following from the SO post:
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
System.out.println(StringUtils.newStringUtf8(Base64.decodeBase64(gmailMessage.payload.parts[0].body.data)));
You can also check this for further reference.
try something like this
public String getMessage(string user_id, string message_id)
{
Message temp =service.Users.Messages.Get(user_id,message_id).Execute();
var parts = temp.Payload.Parts;
string s = "";
foreach (var part in parts) {
byte[] data = FromBase64ForUrlString(part.Body.Data);
s += Encoding.UTF8.GetString(data);
}
return s
}
public static byte[] FromBase64ForUrlString(string base64ForUrlInput)
{
int padChars = (base64ForUrlInput.Length % 4) == 0 ? 0 : (4 - (base64ForUrlInput.Length % 4));
StringBuilder result = new StringBuilder(base64ForUrlInput, base64ForUrlInput.Length + padChars);
result.Append(String.Empty.PadRight(padChars, '='));
result.Replace('-', '+');
result.Replace('_', '/');
return Convert.FromBase64String(result.ToString());
}

RESTEasy: getPathSegments().get(1);

Can someone tell me what "PathSegment model = info.getPathSegments().get(1);" do, specifically, what does he getPathSegments().get(1) mean? Please provide a sample URL for demonstration. The book didn't give an example URL for this one.
Also, is there such a thing as get(0); ?
#Path("/cars/{make}")
public class CarResource
{
#GET
#Path("/{model}/{year}")
#Produces("image/jpeg")
public Jpeg getPicture(#Context UriInfo info)
{
String make = info.getPathParameters().getFirst("make");
PathSegment model = info.getPathSegments().get(1);
String color = model.getMatrixParameters().getFirst("color");
...
}
}
Thanks again,
If you split the path of a URL by a '/' you'll get a list of path-segments. So e.g. the path /cars/ford/mustang/1976 contains the four segments [cars, ford, mustang, 1976]. info.getPathSegments().get(1) should return the segment ford.
The PathSegment holds also the associated MatrixParameters of the current segment. MatrixParameters can be used if you want to filter the resources with a parameter that affects only one segment like here:
/cars/ford/mustang;generation=two/1976

How to iterate over a list of type Class to edit the properties of its objects in Groovy

I know there are more elaborate ways to achieve this in Java, but Groovy should have a concise way to do the same as per http://groovy.codehaus.org/Looping
Class Currency.groovy
class Currency {
String name
double rate
}
CurrencyController
def select(){
List<Currency> selectedCurrencies = Currency.getAll(params.currencies)
selectedCurrencies.eachWithIndex { obj, i -> obj.rate = update(obj.name)};
[selectedCurrencies:selectedCurrencies]
}
def update(String sym){
return sym
}
The above code throws:
No signature of method: currencychecker.CurrencyController$_$tt__select_closure12.doCall() is applicable for argument types: (currencychecker.Currency)
Thanks to #dmahapatro, the issue was that I was using an iterator variable obj[i], even though obj itself is the iterated object. The rest is correct!
I experimented with selectCurrencies.each as well instead of selectCurrencies.eachWithIndex however the right one in this case is eachWithIndex

Resources