Why does the WebhookResponse builder create wrong key in json? - java

I'm trying to utilise com.google.cloud.dialogflow.v2.WebhookResponse to interact with my dialogflow agent. But I'm having trouble responding back to the agent during fulfillment.
The response created doesn't follow the specifications required i.e the agent expect the json to be fulfillmentText: "something" but the builder builds it in the format of fulfillment_text. There's not enough documentation on how to use API client correctly
Anyone has experience doing this in java/kotlin?
val response = WebhookResponse
.newBuilder()
.setFulfillmentText("Hello")
.build()
println(response)
println(Gson().toJson(response))
Output:
fulfillment_text: "Hello"
{"bitField0_":0,"fulfillmentText_":"Hello","fulfillmentMessages_":
[],"source_":"","outputContexts_":[],"memoizedIsInitialized":1,"unknownFields":{"fields":{}},"memoizedSize":-1,"memoizedHashCode":0}
I'm using 'com.google.cloud:google-cloud-dialogflow:0.75.1-alpha' from https://cloud.google.com/dialogflow-enterprise/docs/reference/libraries/java

The library you're using is primarily designed as a client library, letting you send text to Dialogflow and having it determine the Intent and parameters (and possibly a response) from that text.
It sounds like you're trying to use this on the other end - in a webhook to handle fulfillment. It just isn't designed for that. The Class was automatically generated from the ProtoBuf definition, which does not serialize to JSON, and isn't designed to represent things that way.
You will need to build the JSON for the response yourself.

Related

Connecting Akka HTTP directly to an Akka Stream Flow

I've looked through the examples at https://doc.akka.io/docs/akka-http/current/introduction.html for Akka HTTP routing and strangely for something built on top of Akka Streams none of the examples connect to a stream.
Can somebody show a simple example of creating a Java DSL flow (not Scala please), and then connecting a Route directly to that flow?
Or am I missing the point and it's not possible but requires some CompletionStage code within the Route to wait for a result of glue code that calls a Flow?
Edit: to clarify the flow can do something like append a string to a posted request body.
Using akka streams to complete a route is definitely possible. It involves either:
a web socket route, see examples in the docs, or
a chunked http response (since you typically do not know the size of the response if it's fed from a stream). You can create a Chunked Entity from an akka stream Source of ByteStrings
you can also use other response types if the response size is known in advance, see docs for HttpEntity about their specifics
Edit: to clarify the flow can do something like append a string to a posted request body.
MichaƂ's answer contains good links, so please give them a read. Akka HTTP is by default and always streaming with its data -- e.g. the entities. So for example to do a streaming "echo" which at the same time adds a suffix, you could do something like this:
path("test", () ->
// extract the request entity, it contains the streamed entity as `getDataBytes`
extractRequestEntity(requestEntity -> {
// prepare what to add as suffix to the incoming entity stream:
Source<ByteString, NotUsed> suffixSource =
Source.single(ByteString.fromString("\n\nADDS THIS AFTER INCOMING ENTITY"))
// concat the suffix stream to the incoming entity stream
Source<ByteString, Object> replySource = requestEntity.getDataBytes()
.concat(suffixSource);
// prepare and return the entity:
HttpEntity.Chunked replyEntity = HttpEntities.create(ContentTypes.TEXT_PLAIN_UTF8, replySource);
return complete(StatusCodes.OK, replyEntity);
})
);
Having that said, there is numerous ways to make use of the streaming capabilities, including framed JSON Streaming and more. You should also give the docs page about implications of streaming a read.

Deserialize Google Web Kit Response (Java) and Java Servlets

I have a monolithic legacy application that I need to read and submit data to. It's using Google Web Kit and Java Servlets.
I have access to the source code, but I'm new to both Servlets and GWT.
I'm trying to encapsulate a rest client in my project that can communicate with GET/POST rest calls to the legacy server.
I've been able to send a POST request using Postman, and then used Reactive Spring 5.0 framework to sending that request.
When I try to deserialize the response, I'm running into a ton of errors.
How would I deserialize this payload?
7|0|7|http://localhost:8080/testproject/
|29F4EA1240F157649C12466F01F46F60|
com.test.client.GreetingService|greetServer|java.lang.String|
myInput1|myInput2|1|2|3|4|2|5|5|6|7|
I've searched all day, and followed a few blogs like these:
https://docs.google.com/document/d/1eG0YocsYYbNAtivkLtcaiEE5IOF5u4LUol8-LL0TIKU/edit#
https://blog.gdssecurity.com/labs/2009/10/8/gwt-rpc-in-a-nutshell.html
I'm not sure code wise how I can serialize them into my own object for my new service.
static WebClient webClient = WebClient.create();
public static void main(String[] args) {
Mono<String> body = Mono.just("7|0|7|http://localhost:8080/testproject/|29F4EA1240F157649C12466F01F46F60|com.test.client.GreetingService|greetServer|java.lang.String|myInput1|myInput2|1|2|3|4|2|5|5|6|7|");
Mono<String> response = webClient.post()
.uri("http://localhost:8080/testproject/")
.header("Content-Type", "text/x-gwt-rpc;charset=UTF-8")
.header("X-GWT-Module-Base", "http://localhost:8080/testproject/")
.header("X-GWT-Permutation", "29F4EA1240F157649C12466F01F46F60")
.cookie("JSESSIONID", "2BCEBF12GE2C3A0335F5012812A73638")
.body(body, String.class)
.retrieve()
.bodyToMono(String.class);
String unBlocked = response.block();
System.out.println(unBlocked);
//OK[1,1,["java.lang.Integer/3438228391"],0,2]
try {
ServerSerializationStreamReader streamReader = new ServerSerializationStreamReader(
Thread.currentThread().getContextClassLoader(), null);
streamReader.prepareToRead(unBlocked);
System.out.println(streamReader.readObject());
} catch ( Exception e) {
e.printStackTrace();
}
}
Error:
com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: This application is out of date, please click the refresh button on your browser. ( Malformed or old RPC message received - expecting version between 5 and 7 )
I've tried every version of GWT because of the malformed RCP message.
Also, I tried to stick it into a string, which I'm sure is failing on its own.
You are trying to decode the server response with the code meant decode the client request. At present they use a different format for historical reasons - note how the response starts with "//OK", but the request has the version/flags/stringcount "7|0|7" beginning.
In at least a small part this is because when a client calls a server, it needs to describe what version it is speaking and where the server should find the file listing the set of classes that the client expects are allowed to be serialized. When the server responds, since the client already told it about the typed that can be serialized, it doesn't need to tell the client the same thing again.
Reading the com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader class and its docs will show the response format and how it can be decoded into objects. There is presently no server-side code that I'm aware of that is intended to do this job, but could probably be written with fairly little difficulty, just some persistence.

How to log request payload when using Camel Rest?

I'd like to log the original 'raw' request body (e.g. JSON) while using Camel Rest endpoints. What's the proper way to do this?
My setup (RouteBuilder) looks like this:
restConfiguration().component("jetty")
.host(this.host)
.port(this.port)
.contextPath(this.contextPath)
.bindingMode(RestBindingMode.json);
rest("myService/").post()
.produces("application/json; charset=UTF-8")
.type(MyServiceRequest.class)
.outType(MyServiceResponse.class)
.to(SERVICE_CONTEXT_IN);
from(SERVICE_CONTEXT_IN).process(this.serviceProcessor);
My problem here is that the mechanics such as storing the request as an Exchange property are 'too late' in terms of using this approach, any processors are too late in the route, i.e., the binding already took place and consumed the Request. Also the CamelHttpServletRequest's InputStream has already been read and contains no data.
The first place to use the log EIP is directly before the single processor:
from(SERVICE_CONTEXT_IN).log(LoggingLevel.INFO, "Request: ${in.body}")
.process(this.serviceProcessor);
but at that point the ${in.body} is already an instance of MyServiceRequest. The added log above simply yields Request: x.y.z.MyServiceRequest#12345678. What I'd like to log is the original JSON prior to being bound to a POJO.
There seems to be no built-in way of enabling logging of the 'raw' request in RestConfigurationDefinition nor RestDefinition.
I could get rid of the automatic JSON binding and manually read the HTTP Post request's InputStream, log and perform manual unmarshalling etc. in a dedicated processor but I would like to keep the built-in binding.
I agree there is no way to log the raw request (I assume you mean the payload going through the wire before any automatic binding) using Camel Rest endpoints.
But taking Roman Vottner into account, you may change your restConfiguration() as follows:
restConfiguration().component("jetty")
.host(this.host)
.port(this.port)
.componentProperty("handlers", "#yourLoggingHandler")
.contextPath(this.contextPath)
.bindingMode(RestBindingMode.json);
where your #yourLoggingHandler needs to be registered in your registry and implement org.eclipse.jetty.server.Handler. Please take a look at writing custom handlers at Jetty documentation http://www.eclipse.org/jetty/documentation/current/jetty-handlers.html#writing-custom-handlers.
In the end I 'solved' this by not using the REST DSL binding with a highly sophisticated processor for logging the payload:
restConfiguration().component("jetty")
.host(this.host)
.port(this.port)
.contextPath(this.contextPath);
rest("myService/").post()
.produces("application/json; charset=UTF-8")
.to(SERVICE_CONTEXT_IN);
from(SERVICE_CONTEXT_IN).process(this.requestLogProcessor)
.unmarshal()
.json(JsonLibrary.Jackson, MyServiceRequest.class)
.process(this.serviceProcessor)
.marshal()
.json(JsonLibrary.Jackson);
All the requestLogProcessor does is to read the in body as InputStream, get and log the String, and eventually pass it on.
You can solve this by:
Turning the RestBindingMode to off on your specific route and logging the incoming request string as is.
After which you can convert the JSON string to your IN type object using ObjectMapper.
At the end of the route convert the java object to JSON and put it in the exchange out body, as we turned off the RestBindingMode.
rest("myService/").post()
.bindingMode(RestBindingMode.off)
.to(SERVICE_CONTEXT_IN);
In my case, streamCaching did the trick because the Stream was readable only once. Thefore I was able log but was not able to forward the body any more. I hope this might be of help to someone

How to parse serialized json from php web service in java play framework 1.2.x

I need to use some from from a php web service which rendering its data by serializing json in java play framework 1.2.x. What i am doing just using play WS function. and i am getting data from that service. But when I try to get it with JSONObject it throws excepiton which is so normal, because the returned data does not look a json format well. Any body who knows any workarounds or solution would be appreciated.
HttpResponse htp = WS.url("http://www.geoplugin.net/php.gp?ip=78.171.90.49").get();
System.out.println(htp.getContentType()+"\n"+htp.getStatusText()+"\n"+htp.getString());
The returned data :
a:18:{s:17:"geoplugin_request";s:12:"78.171.90.49";s:16:"geoplugin_status";i:200;s:16:"geoplugin_credit";s:145:"Some of the returned data includes GeoLite data created by MaxMind, available from <a href=\'http://www.maxmind.com\'>http://www.maxmind.com</a>.";s:14:"geoplugin_city";s:8:"Istanbul";s:16:"geoplugin_region";s:8:"Istanbul";s:18:"geoplugin_areaCode";s:1:"0";s:17:"geoplugin_dmaCode";s:1:"0";s:21:"geoplugin_countryCode";s:2:"TR";s:21:"geoplugin_countryName";s:6:"Turkey";s:23:"geoplugin_continentCode";s:2:"EU";s:18:"geoplugin_latitude";s:7:"41.0186";s:19:"geoplugin_longitude";s:9:"28.964701";s:20:"geoplugin_regionCode";s:2:"34";s:20:"geoplugin_regionName";s:8:"Istanbul";s:22:"geoplugin_currencyCode";s:3:"TRY";s:24:"geoplugin_currencySymbol";s:15:"YTL";s:29:"geoplugin_currencySymbol_UTF8";s:3:"YTL";s:27:"geoplugin_currencyConverter";s:6:"2.2669";}
You are accessing the PHP endpoint. You need to hit this URL instead:
http://www.geoplugin.net/json.gp?ip=78.171.90.49

Odata with Olingo or Odata4j

I'm in over my head.
At the broadest level, I'm trying to expose an Odata interface to an existing pool of data exposed by a service written using Mule. When my Mule service is invoked, if I detect that the URL is Odata format, I want to delegate processing down to something written in Java and then feed the response from that component back to my caller.
I found the Olingo and OData4j libraries. My problem is that these start from building a Web service. But that's too far upstream for me. I have a Web service. What I need to understand are what components I need to implement in order to pass the URL (which I have in hand) onward to an Odata parser which will, in turn, invoke a data provider.
I'm a bit lost with this technology. Can someone point me to a very basic tutorial that clearly delineates this. Or, can they give me a couple steps like: "You have to implement A, B & C and then pass your URL into C.foo()"?
I've tried the Getting Started doc for both libraries but they both start with "first we'll implement a Web service" and don't clearly delineate (to me, at least) where that leaves off and pure Odata sets in.
Thanks.
The following is the code that will help you to get started for using data from a service exposing via OData.(using Apache Olingo).
URL url=new URL(/*your url*/);
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty(HttpHeaders.ACCEPT,HttpContentType.APPLICATION_XML);
conn.connect();
InputStream content=conn.getInputStream();
Edm edm = EntityProvider.readMetadata(content, false);
After this you can use static methods of EntityProvider class for carrying out various operations like read,update,write
If you are using odata4j go with the following code
ODataConsumer demo_consumer= ODataConsumers.create(/*your URL*/);
Enumerable<EntitySetInfo> demo_entitySetList = demo_consumer.getEntitySets();
for (EntitySetInfo entitySet : entitySetList) {
System.out.println(entitySet.getHref());
}
this sounds very like how we read rss or other data feeds
Since you have a url, this can be read by a Http Connector or even a polling http connector.
The data can be streamed using a Java input stream the default behavior or converted to a string (object to string).
A simple java component using (OData4j) can process your content .. it sounds like 2 simple components on a mule flow.
R

Categories