I am working in a project where a request(ISO 8583) need to be send via JPOS server to the backed (Remote Host as per official doc) via SOAP api.
We have implemented our system as follows:
We implemented a ISOListner in a middle ware(spring boot project) where it converts the incoming ISO message to SOAP request.
Is it possible to embed the Middle ware code to JPOS server itself and omit the mw?
If possible , what is the right place to put our conversion logic ?
Is it the ChannelAdaptor or TransactionManager ?
Few blogs suggest that we can put all logic to TransactionManager or ChannelAdaptor. If it is true
then why we need mux and channel at all? Or our architecture is ok to proceed further ?
For the sake of completeness I will include the answer to this question that was also asked in jPOS Users group (https://groups.google.com/forum/#!topic/jpos-users/PGzb4syQRzs):
We usually implement a custom participant doing the SOAP/REST thing.
In the case of REST, we use Apache's HTTP Client
(org.apache.httpcomponents:httpclient:4.5.5) that provides a nice
async interface that works great with the TransactionManager's PAUSE.
Here is an example:
public int prepare (long id, Serializable o) {
Context ctx = (Context) o;
String url = getURL (ctx);
HttpPost post = new HttpPost(url);
StringEntity entity = new StringEntity(ctx.getString(JSON_REQUEST.name()),ContentType.create("application/json", Consts.UTF_8));
post.setEntity(entity);
try {
client.execute(post, response -> {
int sc = response.getStatusLine().getStatusCode();
if (sc == HttpStatus.SC_CREATED || sc == HttpStatus.SC_OK)
ctx.put (JSON_RESPONSE.name(), EntityUtils.toString(response.getEntity()));
ctx.resume();
return null;
});
return PREPARED | PAUSE | NO_JOIN | READONLY;
} catch (IOException e) {
warn (e);
}
return ABORTED;
}
TransactionManager is the right place to add custom logic. I guess your are using mux and channel to send iso message to MW socket listener component. Which can be avoided by using a middleware like rabbitmq to connect to backend servers.
For example isomessage in transaction manager can be converted to json and send it to backend server using mq.
Related
Our team has developed Server-Sent events (SSE) for a specific task.
I am trying to build a client to listen to event streams from our server.
I have sort of managed to do this using the Jersey libraries for Java.
However since most of our client code uses Spring, I would like to have an example of how this could be done using Spring.
I was able to find many examples on SSE on the server side for Spring. However I am unable to find any documentation for the client side.
Does Spring support SSE on the client side?
If yes, may I have an example of how the following can be achieved using Spring...
Send an HTTP GET request to our server...
GET -> http://example.com/api/events/
headers ->
Accept:text/event-stream
sessionKey:someString
The response will be a text stream, that the client will continue to receive, until the client chooses to close the connection.
Have a look at one of the execute methods of the Spring RestTemplate. They all take a ResponseExtractor as parameter. This callback interface defines one method: extractData(ClientHttpResponse response). By providing your own ResponseExtractor you can do what you want with the response, like reading from it line-by-line. Naive example:
restTemplate.execute(a_url, HttpMethod.GET, request -> {
}, response -> {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getBody()));
String line;
try {
while ((line = bufferedReader.readLine()) != null) {
System.out.println("Got some data, let's use my ObjectMapper to parse into something useful!");
}
} catch (IOException e) {
//Something clever
}
return response;
});
I am currently working on a project where we have multiple microservices on the server side. Which microservices are available to the client changes constantly, as do the location they are available on.
To keep all these changes away from the client, I am working on a REST Router. This would be a single microservice on which knows where each of the other microservices is located. The client can then just talk to this router microservice which will send the request to the correct endpoint.
While this should be fairly straight forward in my opinion, I'm running into al sorts of problems. Since the microservices don't necessarily live on the same host, the router can't simple forward the call, since this only works within the same host.
I am currently trying to make it work by sending a redirect back to the client containing the correct endpoint URL in the location header. But when I try this through restlet, I get a 404 instead of the expected 307 with the location header.
Here's my router code:
#Path("/{any : .*}")
public Response forward(#Context HttpServletRequest request) {
Response response = null;
String requestUri = request.getRequestURI().toString();
String actualUri = requestUri.substring(requestUri.indexOf("route") + 6);
String endpointId = actualUri.substring(0, actualUri.indexOf('/'));
try {
response = redirectTo("http://localhost:8181/api/user/available");
} catch (Throwable e) {
e.printStackTrace();
response = Response.serverError().status(500).build();
}
return response;
}
private Response redirectTo(String path) {
try {
URI uri = new URI(path);
return Response.temporaryRedirect(uri).build();
} catch (URISyntaxException e) {
e.printStackTrace();
return null;
}
}
As far as I can tell, this should work. When I debug the code, I can see that the created Response contains the 307 HTTP status, and the correct location header. But in the client test application (Restlet in Chrome) I keep hitting the 404. When I point restlet directly at the http://localhost:8181/api/user/available I do get the expected result, so the endpoint is available and responding on that address.
Can anyone point me out where I'm going wrong here? Is this really a server issue, or am I missing something in my client software?
When I send a request using a proxy client, if I get a certain response, I would like to be able to modify the request and then send the same request again for all requests.
Normally I would do something like:
BookStore proxy = JAXRSClientFactory.create("http://books", BookStore.class);
try
{
proxy.getBook("someId");
}
catch(WebApplicationException ex)
{
Response r = ex.getResponse();
if (r.getStatusCode() == 404)
{
proxy.getBook("anotherId");
}
}
But in this case, there is a common thing I want to do for all requests: If I get a specific http code, modify some header values, and then try again (probably with a limit on the amount of retries).
I haven't seen a way that cxf proxy clients explicitly support this, how could I go about implementing it?
You need to write an interceptor to do this for every request.
here you go for sample code and documentation http://cxf.apache.org/docs/jax-rs-filters.html
I have an app that makes http requests to a remote server. I do this with the following code:
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("myURL");
try {
ArrayList<BasicNameValuePair> postVariables = new ArrayList<BasicNameValuePair>(2);
postVariables.add(new BasicNameValuePair("key","value"));
httpPost.setEntity(new UrlEncodedFormEntity(postVariables));
HttpResponse response = httpClient.execute(httpPost);
String responseString = EntityUtils.toString(response.getEntity());
if (responseString.contains("\"success\":true")){
//this means the request succeeded
} else {
//failed
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
This goes really well, but one of our customers has set up an APN that requires requests to go via a certain proxy server. If I add the following to the request this works, the request gets rerouted via the proxy to the server:
HttpHost httpHost = new HttpHost("proxyURL",8080);
httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, httpHost);
So far so good, however, I use a library that makes some http requests as well. The library's code is not accesible for me, so I can't add those two lines to the code. I contacted the creators of that library, and they told me it should be possible to set up the android environment so that all requests will automatically go through the proxy. Is there something like that? I didn't find anything on google.
I'm basically looking for a way to set the above two lines as a standard for all http requests. Please note that the APN does not set the proxy as a default for the entire phone, so apps will have to do this manually (and yes that means the majority of the apps don't work on that customer's phone).
It's been a year or two since I've needed to use it, but if I remember correctly, you can use the System.setProperty(String, String) in order to set an environment-wide setting for your application to route all HTTP traffic through a proxy. The properties that you should need to set are "http.proxyHost" and "http.proxyPort" and then use your HttpClient normally without specifying a proxy because the VM will handle routing requests.
Docs for more information about what I'm talking about can be found here: ProxySelector (just so you know what keys to use) and here for documentation about the actual System.setProperty(String, String) function
If that doesn't work for you, let me know and I'll try to dig out my old code that set a system-level proxy. BTW, it's really only "system-level" since each app runs in it's own Dalvik so you won't impact other app's network communications.
I am trying to get the raw XML response from a web service, instead of the usual set of POJOs.
I am using a webservice client that I generated (so I have access to the client's code) from a WSDL and some schemas. The client is generated in RAD 7.5, I think using JAX-WS. I've been looking at the client code itself, but I'm not even sure if the client code ever handles raw XML or if it passes it off to other libraries.
You can do it using
javax.xml.ws.handler.soap.SOAPHandler<javax.xml.ws.handler.soap.SOAPMessageContext>
you can simply get message using SOAPMessageContext#getMessage() and convert message to String using method
public static String getXmlMessage(SOAPMessage message) throws Exception
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
message.writeTo(os);
final String encoding = (String) message.getProperty(SOAPMessage.CHARACTER_SET_ENCODING);
if (encoding == null)
{
return new String(os.toByteArray());
}
else
{
return new String(os.toByteArray(), encoding);
}
}
Also you can read here about SOAP handler on client side
Article
It's not widely documented, but you can use the Dispatch interface to implement JAXWS clients which work directly w/ the XML. Here and here are some articles for getting started.