I'm not too familiar with Anypoint and we will probably only use this program once, I've looked at tutorials on the website but I feel I can't find one that demonstrates the task we have. Basically we are trying to read a JSON file that will be sent to the software, from there we want to use JAVA to read/alter the contents into a desired XML formatting. Finally we then send back or redirect the XML results.
1: I am trying to accept a JSON file from a HTTP POST, I believe I have accomplished this part by using the tutorials and an HTTP element with metadata attached representing the JSON format that may come. Using postman to send the json data as well.
2: From here is where I start to get completely confused. I am wondering what I would need to do in order to pass the data into a Java class object to read the JSON file and begin using Java code (getters/setters) instead of the Anypoint interface in order to start designing the xml layout.
Thanks,
I think the next step is for you to define a model class(with getter/setter), which would represent your json file contents. Since you have already the POST part, the next thing you would do is to use JSON to Object Transformer which the model is injected in.
<json:json-to-object-transformer returnClass="com.alexfrndz.Person" doc:name="JSON to Object"/>
After adding the transformer, you could use a mule custom transformer,
Here is the custom transformer.
package com.alexfrndz;
import org.mule.api.MuleMessage;
import org.mule.api.transformer.TransformerException;
import org.mule.transformer.AbstractMessageTransformer;
public class PersonTransformer extends AbstractMessageTransformer {
#Override
public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException {
Person person = (Person) message.getPayload();
//Do your transformation hear
return null;
}
}
Here is how you implement it,
<custom-transformer class="com.alexfrndz.PersonTransformer" doc:name="PersonTransformer"/>
Hope this will help you.
Related
I am using Anypoint studio.
I have used esper CEP engine for event detection using java file. Once the event is detected i am getting output in the console from java file as system.out.println(Object).
I want the Obejct to be sent from java output to the mule flow either as a message property or payload, so I can store in MongoDB or I can reuse it for another event detection.
here is my flow:
mule flow
Here I want the "event.getUnderlying()" Object to be sent to mule flow.
public void update(EventBean[] newData, EventBean[] oldData) {
EventBean event = newData[0];
obj=event.getUnderlying();
if(a2==0){
i++;
System.out.println("Event received:"+i+" "+event.getUnderlying());
Thanks in Advance :)
Just "post" to the input connector of the flow you want to send to. So for HTTP input use something like org.apache.http.client.HttpClient or HttpUrlConnection
(There are so many examples of how to use those on this site and many others...)
Other inputs have different libraries you can use, you could just save it as a file and have the file input pick it up. (depends on where you are deploying).
If you are calling the Java class via Component (as you mentioned in your comment), your Java class esper.Test_main must be implementing Callable interface. More details on using Java component right - https://docs.mulesoft.com/mule-user-guide/v/3.8/java-component-reference
In that case, you need to implement below method:
public Object onCall(MuleEventContext eventContext) {
//your code here
return someObject; // return event.getUnderlying() in your case
}
The object returned from onCall() method is passed on as 'payload' to the next message processor in mule flow.
If you need to set a flow variable from the Java class:
public Object onCall(MuleEventContext eventContext) {
//your code here
eventContext.getMessage().setInvocationProperty("variableName", "variableValue");
return someObject; // return event.getUnderlying() in your case
}
Now, you will have a flowVar called variableName available in your mule flow.
HTH.
I am currently working on a REST based java application using the new Camel REST DSL as the foundation.
It mostly works except that I noticed when calling the URLs through a REST client (instead of say a browser) the JSON response is "garbled" and comes through with what I assume is the wrong encoding
MyRouteBuilder.java
#Component
public class MyRouteBuilder extends RouteBuilder{
#Autowired
LocalEnvironmentBean environmentBean;
#Override
public void configure() throws Exception {
restConfiguration().component("jetty").host("0.0.0.0").port(80)
.bindingMode(RestBindingMode.auto);
rest("/testApp")
.get("/data").route()
.to("bean:daoService?method=getData")
.setProperty("viewClass", constant(CustomeJsonViews.class))
.marshal("customDataFormat").endRest()
.get("/allData").route()
.to("bean:daoService?method=getDatas")
.setProperty("viewClass", constant(CustomeJsonViews.class))
.marshal("customDataFormat").endRest();
}
}
CustomeDataFormat.java
public class CustomDataFormat implements DataFormat{
private ObjectMapper jacksonMapper;
public CustomDataFormat(){
jacksonMapper = new ObjectMapper();
}
#Override
public void marshal(Exchange exchange, Object obj, OutputStream stream) throws Exception {
Class view = (Class) exchange.getProperty("viewClass");
if (view != null)
{
ObjectWriter w = jacksonMapper.writerWithView(view);
w.writeValue(stream, obj);
}
else
stream.write(jacksonMapper.writeValueAsBytes(obj));
}
#Override
public Object unmarshal(Exchange exchange, InputStream stream) throws Exception {
return null;
}
}
A full working version can be found here:
https://github.com/zwhitten/camel-rest-test
When going to the URL, {host}/testApp/data, in Chrome for example the response comes through as:
{
data: "Sherlock",
value: "Holmes",
count: 10
}
However using the Postman browser plugin as the client returns:
"W3siZGF0YSI6ImRhdGE6OjAiLCJ2YWx1ZSI6InZhbHVlOjowIiwiY291bnQiOjB9LHsiZGF0YSI6ImRhdGE6OjEiLCJ2YWx1ZSI6InZhbHVlOjoxIiwiY291bnQiOjF9LHsiZGF0YSI6ImRhdGE6OjIiLCJ2YWx1ZSI6InZhbHVlOjoyIiwiY291bnQiOjJ9LHsiZGF0YSI6ImRhdGE6OjMiLCJ2YWx1ZSI6InZhbHVlOjozIiwiY291bnQiOjN9LHsiZGF0YSI6ImRhdGE6OjQiLCJ2YWx1ZSI6InZhbHVlOjo0IiwiY291bnQiOjR9LHsiZGF0YSI6ImRhdGE6OjUiLCJ2YWx1ZSI6InZhbHVlOjo1IiwiY291bnQiOjV9LHsiZGF0YSI6ImRhdGE6OjYiLCJ2YWx1ZSI6InZhbHVlOjo2IiwiY291bnQiOjZ9LHsiZGF0YSI6ImRhdGE6OjciLCJ2YWx1ZSI6InZhbHVlOjo3IiwiY291bnQiOjd9LHsiZGF0YSI6ImRhdGE6OjgiLCJ2YWx1ZSI6InZhbHVlOjo4IiwiY291bnQiOjh9LHsiZGF0YSI6ImRhdGE6OjkiLCJ2YWx1ZSI6InZhbHVlOjo5IiwiY291bnQiOjl9XQ=="
The problem seems to be with the REST bind mode being "auto" and using a custom marshaller.
If I set the binding mode to "json" then both the browser and client responses get garbled.
If I set the binding mode to "json" and bypass the custom marshallers everything works correctly.
Is there a way to configure the route to use a custom marshaller and encode the responses correctly regardless of the client?
I think the solution is to use the default binding option(off) since you are using custom marshallers.
You have two ways to achieve it:
Turn off the RestBindingMode, because otherwise the RestBindingMarshalOnCompletion in RestBindingProcessor will be registered and manually (un)marshal.
Register your own DataFormat and use it within the RestBinding automatically. You configure the REST configuration via jsonDataFormat to set the custom data format.
Map<String, DataFormatDefinition> dataFormats = getContext().getDataFormats();
if (dataFormats == null) {
dataFormats = new HashMap<>();
}
dataFormats.put("yourFormat", new DataFormatDefinition(new CustomDataFormat()));
restConfiguration()....jsonDataFormat("yourFormat")
You can also create your own dataformat like so:
in your restconfiguration it will look sthg like this (see json-custom)
builder.restConfiguration().component("jetty")
.host(host(propertiesResolver))
.port(port(propertiesResolver))
.bindingMode(RestBindingMode.json)
.jsonDataFormat("json-custom")
;
You must create a file "json-custom"
that's the name of the file and that file should contain the class name that implements your own way to marshal and unmarshal...
it must be located in your jar : META-INF\services\org\apache\camel\dataformat
so the content of the file should be:
class=packageofmyclass.MyOwnDataformatter
The response you were receiving is JSON, but it had been encoded to base64. Taking the String from your post, I was able to decode it as:
[{"data":"data::0","value":"value::0","count":0},{"data":"data::1","value":"value::1","count":1},{"data":"data::2","value":"value::2","count":2},{"data":"data::3","value":"value::3","count":3},{"data":"data::4","value":"value::4","count":4},{"data":"data::5","value":"value::5","count":5},{"data":"data::6","value":"value::6","count":6},{"data":"data::7","value":"value::7","count":7},{"data":"data::8","value":"value::8","count":8},{"data":"data::9","value":"value::9","count":9}]
The answers above stop the response body being encoded to base64. The documentation from Apache Camel on bindingMode is illusive as to why it behaves that way when combined with explicit marshalling. Removing the explicit marshalling will return a JSON body, but you may also notice that it contains the any class names in the body. The documentation suggests that bindingMode is more for the transportation of classes and that you specifiy a type(Pojo.class) and optionally outType(Pojo.class) of your requests/responses. See http://camel.apache.org/rest-dsl.html (section Binding to POJOs Using) for more details.
Base64 is the safest way of transferring JSON across networks to ensure it is received exactly as the server sent it, according to some posts I've read. It is then the responsibility of the client to then decode the response.
The answers above do solve the problem. However, I'm not entirely convinced that mixing the data format in the service routes is such as good thing and should ideally be at a higher level of abstraction. This would then allow the data format to be changed in one place, rather than having to change it on every route that produces JSON. Though, I must admit, I've never seen a service that has change data format in its lifetime, so this really is a mute point.
We were also facing the same issue.
Our DataFormat was Json .Once we implented our own custom marshaller. Camel was encoding the data to base64.I tried the approach provided by Cshculz but our CustomDataFormatter was not getting called for some reason which i couldn't figure out.
So We added .marshal(YourDataFormatter) after every Bean call.This provided us with the formatted json but in the encoded form so in the end of the route we added .unmarshal().json(JsonLibrary.Jackson) to return a raw json to the client.
sample snippet :-
.to("xxxxxxx").marshal(YourDataFormatterBeanRef)
.to("xxxxxxx").marshal(YourDataFormatterBeanRef)
.to("xxxxxxx").marshal(YourDataFormatterBeanRef)
.to("xxxxxxx").marshal(YourDataFormatterBeanRef)
.end().unmarshal().json(JsonLibrary.Jackson)
I'm having a problem where my C# client can't parse the data from my webservice in Glassfish.
I have a WSDL and XSD for my webservices as follows:
http://www.consorciovivedigital.com:8080/ServicioInterventoria/ServicioInterventoria?WSDL
http://www.consorciovivedigital.com:8080/ServicioInterventoria/ServicioInterventoria?xsd=1
And I'm using the next C# client to test this webservice:
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using ServicioInterventoria;
public partial class _Default : System.Web.UI.Page
{
ServicioInterventoria.ServicioInterventoria proxy;
protected void Page_Load(object sender, EventArgs e)
{
proxy = new ServicioInterventoria.ServicioInterventoria();
ResultadoMensualIC[] res = proxy.ObtenerResultadosMensuales("Intv12", "2014-07-07T08:08:08");
System.Diagnostics.Debug.WriteLine(res.Length);
System.Diagnostics.Debug.WriteLine(res[0].FechaCorte);
}
}
The problem is that when I execute this code, the res array has the amount of objects that should have, but each value of each object has the default value instead of the correct value. I used Fiddler to check the traffic and it receives the correct SOAP response with the correct data, but it seems that my C# client doesn't know how to parse the data.
I checked with a Java client, and I can get the correct data without any problems, and seems that my C# it's the only one giving problems with this.
Maybe there is a problem with the targetNamespace in the SOAP response, but I don't understand why works correctly in Java but in C# just puts default values.
Anyone have any idea what could be the problem?
If someone needs more information about it, let me know
Thanks beforehand
I solved last week. The problem was that the SOAP response didn't put the namespace for each attribute, then, the C# client doesn't know how to match this (seems like a limitation of C#). And, the other problem was the order of the SOAP response, because, the C# client was expecting each object as was defined in the WSDL, but the response it's ordered alphabetically, in this way, the C# client, doesn't match correctly each attribute.
I did some modifications to the client. First, in each model, for each attribute I added the namespace, something like this:
#XmlElement(name = "IdInterventor", namespace = "http://ws.bigdatasolutions.co/")
public String getIdInterventor() {
return IdInterventor;
}
With this, the SOAP response always puts the namespace for each attribute, which was neccesary for the C# client.
After that, at the beginning of each model class I add this tag, to define the order as defined in the WSDL and expected for the C# client.
#XmlRootElement(name = "AspectosFinancieros")
#XmlType(propOrder={"idInterventor", "numeroContrato", "ano", "valorContratoOperador", "fechaFirmaContrato",
"valorAdicion", "fechaProrrogaAdicion", "valorDesembolso", "fechaPagoDesembolso",
"valorAnticipo", "fechaAnticipo", "valorUtilizacion", "numeroActaAprobacion",
"fechaUtilizacion", "valorRendimiento", "fechaRendimiento", "numeroComprobanteRendimiento",
"valorComision", "fechaComision", "valorGastosAdministrativos", "fechaGastosAdministrativos",
"nombreFiducia", "numeroContratoFiducia", "fechaContratoFiducia", "fechaProrrogaAdicionFiducia",
"marcaTiempo"})
public class AspectosFinancieros {
I checked the expected order in the auto generated class in the C# client.
I hope someone find this useful.
I am developing an Android app using GAE on Eclipse.
On one of the EndPoint classes I have a method which returns a "Bla"-type object:
public Bla foo()
{
return new Bla();
}
This "Bla" object holds a "Bla2"-type object:
public class Bla {
private Bla2 bla = new Bla2();
public Bla2 getBla() {
return bla;
}
public void setBla(Bla2 bla) {
this.bla = bla;
}
}
Now, my problem is I cant access the "Bla2" class from the client side. (Even the method "getBla()" doesn't exist)
I managed to trick it by creating a second method on the EndPoint class which return a "Bla2" object:
public Bla2 foo2()
{
return new Bla2();
}
Now I can use the "Bla2" class on the client side, but the "Bla.getBla()" method still doesn't exit. Is there a right way to do it?
This isn't the 'right' way, but keep in mind that just because you are using endpoints, you don't have to stick to the endpoints way of doing things for all of your entities.
Like you, I'm using GAE/J and cloud endpoints and have an ANdroid client. It's great running Java on both the client and the server because I can share code between all my projects.
Some of my entities are communicated and shared the normal 'endpoints way', as you are doing. But for other entities I still use JSON, but just stick them in a string, send them through a generic endpoint, and deserialize them on the other side, which is easy because the entity class is in the shared code.
This allows me to send 50 different entity types through a single endpoint, and it makes it easy for me to customize the JSON serializing/deserializing for those entities.
Of course, this solution gets you in trouble if decide to add an iOS or Web (unless you use GWT) client, but maybe that isn't important to you.
(edit - added some impl. detail)
Serializing your java objects (or entities) to/from JSON is very easy, but the details depend on the JSON library you use. Endpoints can use either Jackson or GSON on the client. But for my own JSON'ing I used json.org which is built-into Android and was easy to download and add to my GAE project.
Here's a tutorial that someone just published:
http://www.survivingwithandroid.com/2013/10/android-json-tutorial-create-and-parse.html
Then I added an endpoint like this:
#ApiMethod(name = "sendData")
public void sendData( #Named("clientId") String clientId, String jsonObject )
(or something with a class that includes a List of String's so you can send multiple entities in one request.)
And put an element into your JSON which tells the server which entity the JSON should be de serialized into.
Try using #ApiResourceProperty on the field.
I'm trying to build a Java REST web service that will do some processing on a get request (eg. send get request with info, do some calculations, then send back an object with the results). Any ideas how I can set this up easily in Netbeans? I've been playing with the New->RESTful web service... feature, but can't seem to get it to return an object.
AFAIK you're supposed to return a string representation of the result. For example implementing the getXml() method:
/**
* Retrieves representation of an instance of services.GenericResource
* #return an instance of java.lang.String
*/
#GET
#Produces("application/xml")
public String getXml() {
return "<entry></entry>";
}
You could use an XML API to turn your objects into XML strings and return them.
What kind of object do you want to return...?
In java rest webservice you can return many kinds of objects like json,xml.
You can follow these tutorials for creating any kind of java rest webservice -
http://www.mkyong.com/webservices/jax-rs/json-example-with-jersey-jackson/
This link shows example of get request which returns a json object. You can browse there tutorials for any other requirements.
I haven't tried it in Netbeans, but I have done it using Intellij tho, using maven. Just used servlets to get the requests and used GSON to convert the outgoing java object to JSON and send it out.
This is the project I did with some of my colleges.