SOAP result null? - java

I have problem with my soap client. I have generate client part from wsdl using apache cxf.
I'm using Netbeans IDE and Maven. I also created HeaderHandler where I print soap response and it seems to be valid. But when I call web service method from my client a always get null value without any exception.
Any idea?
Thanks.
Update:
link to wsdl http://carecoprod.blueway.fr:8180/engine53/52/WSDL?name=AAA00_WsB2B&version=1&type=EAII
Client code:
{
AAA00WsB2B ss = new AAA00WsB2B(wsdlURL, SERVICE_NAME);
HeaderHandlerResolver h = new HeaderHandlerResolver();
ss.setHandlerResolver(h);
AAA00WsB2BPortType port = ss.getAAA00WsB2BPort();
System.out.println("Invoking aaa00WsB2B...");
AAA00WsB2BIN input = new AAA00WsB2BIN();
VarAAA v = new VarAAA();
v.setLogin("*******");
v.setImmat("*******");
v.setTypeReq("******");
v.setMdp("*******");
input.setVarAAA(v);
AAA00WsB2BOUT _aaa00WsB2B__return = new ObjectFactory().createAAA00WsB2BOUT();
_aaa00WsB2B__return = port.aaa00WsB2B(input);
System.out.println("aaa00WsB2B.result="+_aaa00WsB2B__return.getVarAAARetourWs().getCO2());
}

Related

JAX-WS sending empty value after explicitly adding SOAPAction header

I have made webservice client with NetBeans 8.2 wizard from an existing WSDL document. Java8 and JAX-WS 2.2.9 is used.
As far as I understand everything works with the wizard created code as expected but the query is missing value from "SOAPAction" header which is requirement to have value for the query to work. The header key exists but value is empty string: SOAPAction: "" when it should be SOAPAction = "SendReports"
I have tried using this:
Map<String, List<String>> requestHeaders = new HashMap<>();
requestHeaders.put("SOAPAction", Arrays.asList("sendReports"));
sourceDispatch.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders);
-> which results also in empty value. If I put "SOAPAction_2" & "sendReports", that header works correct but obviously the header key is wrong and wont solve my problem. Something overwrites my value afterwards?
The webservice method has annotation:
#WebMethod(operationName = "SendReports", action = "SendReports")
Any tips on what could I try next?
I saw many posts suggesting using BindingProvider but I cannot use com.sun.* packages for reasons left unexplained.
Finally found a working solution.
I created a Web service Dispatch client with Netbeans (as originally) and had to add SOAPACTION_USE_PROPERTY and SOAPACTION_URI_PROPERTY.
These I had tried before as System properties but seemed not to work that way.
Here is the working snippet:
public void sendReports() throws IOException {
ReportService service = new ReportService();
QName portQName = new QName("http://URL/ReportService", "ReportService");
req = readFile("C:/temp/myFile.xml", "UTF-8");;
try {
// Call Web Service Operation
Dispatch<Source> sourceDispatch = null;
sourceDispatch = service.createDispatch(portQName, Source.class, Service.Mode.PAYLOAD);
Map<String, Object> map = sourceDispatch.getRequestContext();
map.put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
map.put(BindingProvider.SOAPACTION_URI_PROPERTY, "SendReports");
Source result = sourceDispatch.invoke(new StreamSource(new StringReader(req)));
} catch (Exception ex) {
// TODO handle custom exceptions here
}
}

Access GoogleCloudStorage using GoogleCloudEndpoints

I'm working on this project in which I'm using a Google-App-Engine backend connected to an Android app via Google-Cloud-Endpoints. For Google-Cloud-Datastore access I'm using Objectify and everything works fine.
Now I decided to add the functionality to upload images to Google-Cloud-Storage but I couldn't find a clear explanation on how to do this using the Google-Cloud-Endpoints setup.
I found the following explanation how to use Google-Cloud-Storage with Google-App-Engine:
https://cloud.google.com/appengine/docs/java/googlecloudstorageclient/app-engine-cloud-storage-sample
but instead of adding it to the Endpoints Api the article writes an additional servlet.
Furthermore I found this example of upload/download for Android:
github.com /thorrism/GoogleCloudExample
Sadly this is using the Google Cloud Storage API for direct access to the Google-Cloud-Storage and you need to add a P12-file to the asset folder, which seems unsecure.
My Google-App-Engine code looks like that:
#Api(
name = "example",
version = "v1",
scopes = { Constants.EMAIL_SCOPE },
clientIds = { Constants.WEB_CLIENT_ID, Constants.ANDROID_CLIENT_ID, Constants.API_EXPLORER_CLIENT_ID },
audiences = {Constants.ANDROID_AUDIENCE},
description = "API for the Example Backend application."
)
public class ExampleApi{
#ApiMethod(name = "doSomething", path = "dosomething", httpMethod = HttpMethod.POST)
public String doSomething(#Named("text") String text){
TestEntity test = new TestEntity(text);
ofy().save().entity(test).now();
return test;
}
After I uploaded it I generated the Endpoints Client Library and imported it into my android project.
Then I'm calling Endpoints from Android like explained here:
https://cloud.google.com/appengine/docs/java/endpoints/calling-from-android#creating_the_service_object
public static com.appspot.******.example.Example buildServiceHandler(Context context, String email) {
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(
context, AppConstants.AUDIENCE);
credential.setSelectedAccountName(email);
com.appspot.******.example.Example.Builder builder = new com.appspot.******.example.Example.Builder(
AppConstants.HTTP_TRANSPORT,
AppConstants.JSON_FACTORY, null);
builder.setApplicationName("example-server");
return builder.build();
}
sApiServiceHandler = buildServiceHandlerWithAuth(context,email);
And each Api-Method I call like this:
com.appspot.******.example.Example.DoSomething doSomething = sApiServiceHandler.doSomething(someString);
doSomething.execute();
All of this works fine, but only for storing/receiving Datastore Entities. How would I go about uploading/downloading files to Google Cloud Storage using the Google Cloud Endpoints setup?
Is it somehow possible to send a POST with my image data via Endpoints to the UploadServlet using the already build ServiceHandler ?
Is it possible to call a servlet from an Endpoints Method? How am I supposed to send the Post to the Servlet and how would I go about the authentication?
Any help or advice would be greatly appreciated!
There are different ways to do this, but the most recommended way is to use Signed URLs, so that your Android app can upload the file securely to Google Cloud Storage directly, without going through your Endpoints backend. The basic process is:
1) Create an Endpoints method that creates a new signed URL and returns it to the Android client. Signing the URL on the server still requires a P12 key but is stored on App Engine, not on the client, so is secure. Try to use a short expiration for the URL, for example no more than 5 minutes.
2) Have the Android client upload the file directly to the signed URL, as you would doing a normal HTTP PUT to the Cloud Storage XML API to upload a file (resumable uploads with the JSON API are also supported, but not covered here).
Your Endpoints method might look like this:
#ApiMethod(name = "getUploadUrl", path = "getuploadurl", httpMethod = HttpMethod.GET)
public MyApiResponse getUploadUrl(#Named("fileName") String fileName
#Named("contentType" String contentType)
{
String stringToSign
= "PUT\n" + contentType
+ "\n" + EXPIRATION_TIMESTAMP_EPOCH_SECONDS + "\n"
+ YOUR_GCS_BUCKET + "/" + fileName;
// Load P12 key
FileInputStream fileInputStream = new FileInputStream(PATH_TO_P12_KEY);
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(fileInputStream, password);
PrivateKey key = keyStore.getKey(privatekey", YOUR_P12_KEY_PASSWORD);
// Get signature
Signature signer = Signature.getInstance("SHA256withRSA");
signer.initSign(key);
signer.update(stringToSign.getBytes("UTF-8"));
byte[] rawSignature = signer.sign();
String signature = new String(Base64.encodeBase64(rawSignature, false), "UTF-8");
// Construct signed url
String url
= "http://storage.googleapis.com/" + YOUR_GCS_BUCKET + fileName
+ "?GoogleAccessId=" + P12_KEY_SERVICE_ACCOUNT_CLIENT_ID
+ "&Expires=" + EXPIRATION_TIMESTAMP_EPOCH_SECONDS
+ "&Signature=" + URLEncoder.encode(signature, "UTF-8");
// Endpoints doesn't let you return 'String' directly
MyApiResponse response = new MyApiResponse();
response.setString(url);
return response;
}
On the Android side, you might use the method like this:
// Get the upload URL from the API
getUploadUrl = sApiServiceHandler.getUploadUrl(fileName, contentType);
MyApiResponse response = getUploadUrl.execute();
String uploadUrl = response.getString();
// Open connection to GCS
URL url = new URL(uploadUrl);
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setDoOutput(true);
httpConnection.setRequestMethod("PUT");
httpConnection.setRequestProperty("Content-Type", contentType);
// Write file data
OutputStreamWriter out = new OutputStreamWriter(httpConnection.getOutputStream());
out.write(fileData);
out.flush();
// Get response, check status code etc.
InputStreamReader in = new InputStreamReader(httpConnection.getInputStream());
// ...
(Disclaimer: I'm just typing code freely into a text editor but not actually testing it, but it should be enough to give you a general idea.)

Setting connection's `max_frame_size` in Qpid Proton AMQP 1.0 client library

I would like to simply open an AMQP 1.0 connection with a specific max_frame_size using the Apache Qpid Proton client library. This is inside a testsuite, not a real world application.
The Java library seems more advanced than the C library and its various bindings for other languages, so I started to use the Java one. Unfortunately, I can't find a way to set this parameter, though there must be a way: there is this Transport class which offers to get or set max_frame_size.
I first tried with the Messenger API, then I played with the Engine API. I couldn't figure out how to access the transport instance. In the case of the Engine API, I see there is a Connection.getTransport() and tried that, but it's NULL at the time I call this function.
Here is my last test:
private void do_test_with_frame_size(int frame_size, int payload_size) {
Connection conn = Connection.Factory.create();
Transport transport = conn.getTransport();
transport.setMaxFrameSize(frame_size);
Session session = conn.session();
Sender sender = session.sender("sender");
conn.open();
session.open();
sender.open();
if (sender.getCredit() > 0) {
String uri = System.getProperty("broker_uri");
assertNotNull(uri);
String address = String.format("%s/fragmentation-%d-%d",
uri, frame_size, payload_size);
Message message = Proton.message();
message.setAddress(address);
message.setBody(new AmqpValue(new byte[payload_size]));
byte[] msgData = new byte[1024];
int length;
while(true) {
try {
length = message.encode(msgData, 0, msgData.length);
break;
} catch(BufferOverflowException e) {
msgData = new byte[msgData.length * 2];
}
}
byte[] tag = "0".getBytes();
Delivery delivery = sender.delivery(tag);
sender.send(msgData, 0, length);
delivery.settle();
sender.advance();
sender.close();
sender.getSession().close();
sender.getSession().getConnection().close();
}
}
I admit I have very limited knowledge of Java. Could you please confirm it is even possible to set this parameter and, if yes, tell me how to?
You need to create a Transport instance for the connection to use and then bind the transport to the connection instance. A created Connection does not have an implicit Transport bound to it which is why you get a null returned to you currently.
private final Transport protonTransport = Proton.transport();
private final Connection protonConnection = Proton.connection();
...
this.protonTransport.setMaxFrameSize(maxFrameSize);
this.protonTransport.setChannelMax(CHANNEL_MAX);
this.protonTransport.bind(this.protonConnection);

How do I send JSON to an external API using RestEasy?

I need to send a JSON body to https://mandrillapp.com/api/1.0//messages/send-template.json . How do I do this using RestEasy in Java? This is what I have so far:
ResteasyClient client = new ResteasyClientBuilder().build();
ResteasyWebTarget target = client.target("https://mandrillapp.com/api/1.0//messages/send-template.json");
How do I actually send the JSON?
Once you have the ResteasyWebTarget, you need to get the Invocation
Invocation.Builder invocationBuilder = target.request("text/plain").header("some", "header");
Invocation incovation = invocationBuilder.buildPost(someEntity);
invocation.invoke();
where someEntity is some instance of Entity<?>. Create one with
Entity<String> someEntity = Entity.entity(someJsonString, MediaType.APPLICATION_JSON);
Read this javadoc.
This is for 3.0 beta 4.
This is a bit old question, but I found it looking for something similar on Google, so this is my solution, using RestEasy client 3.0.16:
I'll use a Map object to be sent but you can use whatever JavaBean that Jackson provider can convert to JSON.
BTW, you'll need add as dependency the resteasy-jackson2-provider lib.
ResteasyClient client = new ResteasyClientBuilder().build();
ResteasyWebTarget target = client.target("http://server:port/api/service1");
Map<String, Object> data = new HashMap<>();
data.put("field1", "this is a test");
data.put("num_field2", 125);
Response r = target.request().post( Entity.entity(data, MediaType.APPLICATION_JSON));
if (r.getStatus() == 200) {
// Ok
} else {
// Error on request
System.err.println("Error, response: " + r.getStatus() + " - "+ r.getStatusInfo().getReasonPhrase());
}
I've never used this framework, but according to an example at this url, you should be able to make a call like this:
Client client = ClientBuilder.newBuilder().build();
WebTarget target = client.target("http://foo.com/resource");
Response response = target.request().get();
String value = response.readEntity(String.class);
response.close(); // You should close connections!
The 3rd line seems to be the answer you're looking for.

HttpPost not sending params once over a certain size

Here is the code:
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(SERVER_URL);
NameValuePair[] data = {
new NameValuePair("html", html)
};
method.setRequestBody(data);
Once the value for the html var goes over a certain size all params become null for the receiving URL. Any ideas why?
This doesn't sound like a fault on the client side. I suspect that you may be hitting a server-side limit; e.g. a request-size limit specified in the web container configuration ... or a front-end.

Categories