CXF Header element with String - java

I'm trying to construct a simple header element (i.e. contextID) with org.apache.cxf.headers.Header
The XML representation should be like:
<soapenv:Header>
<contextID>someString</contextID>
</soapenv:Header>
I was trying like this in an interceptor:
String contextID = "someString";
List<Header> headers = message.getHeaders();
//this could be possibly wrong
Header contextIdHeader = new Header(new QName(CORE_NAMESPACE, "contextID"), contextID);
headers.add(contextIdHeader);
message.put(Header.HEADER_LIST, headers);
But I'm getting an exception:
java.lang.ClassCastException: java.lang.String cannot be cast to org.w3c.dom.Element
I suppose, the construction of the Header element is wrong.
What would be the correct way to do it?
Thank you!

Found the solution:
the Header element has to be created like this
Header contextIdHeader = new Header(new QName(CORE_NAMESPACE, "contextID"), contextID, new JAXBDataBinding(String.class));

Related

How do I return Http Response Content Length for ResponseEntity<List<Object>> without formatting issues or losing data from my response body?

I'm trying to set the content length of my ResponseEntity<List> but the full list isn't returned in the response. I tried something like
long contentLength = staticMethodGetsContentLength(List<Object> objectList);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Length", String.valueOf(contentLength));
return Response.ok().headers(headers).body(objectList);
and then what is returned is a JSON list like
[
{
"data": "data"
without closing brackets or the full list of objects. Is there an easy fix for this or an alternative to what I'm doing?

HttpRequest.BodyPublishers.ofString(jsonasstring) does not put anything in the POST request

I'm trying to make a POST request with custom headers and json as string on body
Here's my code
HttpRequest request2 = HttpRequest.newBuilder()
.uri(URI.create(POSTS_API_URL))
.headers("accept", "text/plain; charset=UTF-8", "XF-Api-Key", "MYAPIKEY")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
System.out.println(request2); //result : https://******.fr/api/auth/ POST
System.out.println(request2.headers()); //result : java.net.http.HttpHeaders#8e33ff08 { {accept=[text/plain; charset=UTF-8], XF-Api-Key=[MYAPIKEY]} }
HttpResponse<String> response2 = client.send(request2, HttpResponse.BodyHandlers.ofString());
// print status code
System.out.println(response2.statusCode()); //400
// print json code
System.out.println(json); //{"login":"LunaLune","password":"***********"}
// print response body
System.out.println(response2.body()); //mandatory input missing : login, password
And my json String
String json = "{" +
"\"login\":\"LunaLune\"," +
"\"password\":\"*********\"" +
"}";
But when I print the request I get : https://*******.fr/api/auth/ POST
the POST request is empty
I googled many forums, code examples ect... but I see that my code where correct according many examples I seen.
So if someone know what is my problem ?
Thanks in advance !
You need to set "Content-Type" as "application/json" in the request header.
See: Which JSON content type do I use?

Post multipart file and JSON in Rest Assured

I need to send a video file and JSON object in Rest Assured post call.
Structure is like the following:
{ "sample" : {
"name" : "sample-name",
"kind" : "upload",
"video_file" : multipart file here } }
So I did like the following
Code:
given()
.header("Accept", "application/json")
.header(auth)
.config(rConfig)
.body(body)
.multiPart("sample[video_file]", new File("path"), "video/mp4")
.formParam("sample[name]", "Video Upload")
.formParam("sample[kind]", "upload")
.log().all().
expect()
.statusCode(expectedStatusCode)
.post(url);
I can't use application/JSON while using multipart in Rest Assured. I explicitly hardcoded the value in the form param and sent the media file in multipart and now it is working fine.
How can I send all the form param data in a single inner object.
You can do this by using RequestSpecBuilder. It supports all the request parameters and you can easily create multipart request.
Sample code taken from https://github.com/rest-assured/rest-assured/wiki/Usage
RequestSpecBuilder builder = new RequestSpecBuilder();
builder.addParam("parameter1", "parameterValue");
builder.addHeader("header1", "headerValue");
RequestSpecification requestSpec = builder.build();
given().
spec(requestSpec).
param("parameter2", "paramValue").
when().
get("/something").
then().
body("x.y.z", equalTo("something"));
Thanks for your response rohit. I was post this question for handling inner object with formParams. I've completed by creating a Hash Map for formParams. Because formParams method of rest assured can accept Hash map.
Form params map creation:
private static Map<String, String> createFormParamsMap(VideoTagInput videoTag) {
Map<String, String> formParams = new HashMap<>();
formParams.put(createFormParamKey("name"), "name");
formParams.put(createFormParamKey("kind"), "kind");
return formParams;
}
private static String createFormParamKey(String paramKey) {
return "sample[" + paramKey + "]";
// output is like "sample[name]" - I'm forming inner object here for my purpose.
}
Finally send the map to Rest Assured post call function
given()
.header("Accept", "application/json")
.header(auth)
.config(rConfig)
.multiPart("sample[video_file]", new File("path"), "video/mp4")
.formParams(requestParamsMap) // requestParamsMap here.
.log().all().
expect()
.statusCode(expectedStatusCode)
.post(url);
Your approach is definitely not standard.
You cannot have a multipart request and a JSON body, you need to pick one over the 2 approaches: multipart/form-data or application/json request.
The standard way is to have a multipart request with a "json" param containing the serialized JSON payload, and a "file" param with the multipart file.
given()
.contentType(MediaType.MULTIPART_FORM_DATA_VALUE)
.multiPart(file)
.param("json", "{\"sample\":{\"name\":\"sample- name\",\"kind\":\"upload\",\"video_file\":<this is not needed>}}")
But this involves changing your server-side logic.
If you cannot change your server-side logic, you need to serialize your file as (for instance as an array of bytes, or as base64 string) to be set as video_file in your JSON payload. In which case you'll have an application/json content type request, not a 'multipart/form-data'.

Connecting to Odata 4 returns 406 Not Acceptable

I am trying to connect to Odata 4 and I got a 406 error.
The content-type range '[application/json;odata.metadata=full]' is not supported. [HTTP/1.1 406 Not Acceptable]
Full stacktrace:
Exception in thread "main" org.apache.olingo.client.api.communication.ODataClientErrorException: The content-type range '[application/json;odata.metadata=full]' is not supported. [HTTP/1.1 406 Not Acceptable]
at org.apache.olingo.client.core.communication.header.ODataErrorResponseChecker.checkResponse(ODataErrorResponseChecker.java:73)
at org.apache.olingo.client.core.communication.request.AbstractRequest.checkResponse(AbstractRequest.java:53)
at org.apache.olingo.client.core.communication.request.AbstractODataRequest.doExecute(AbstractODataRequest.java:324)
at org.apache.olingo.client.core.communication.request.retrieve.ODataServiceDocumentRequestImpl.execute(ODataServiceDocumentRequestImpl.java:57)
at org.apache.olingo.client.core.communication.request.retrieve.ODataServiceDocumentRequestImpl.execute(ODataServiceDocumentRequestImpl.java:37)
at com.acc.odata.OlingoConnect.main(OlingoConnect.java:23)
Below is the code i am trying to get the connection to odata using olingo jars
String serviceRoot = "http://localhost:8080/odata-server-sample/cars.svc";
ODataClient client = ODataClientFactory.getV4();
ODataServiceDocumentRequest req = client.getRetrieveRequestFactory()
.getServiceDocumentRequest(serviceRoot);
ODataRetrieveResponse<ODataServiceDocument> res = req.execute();
ODataServiceDocument serviceDocument = res.getBody();
Collection<String> entitySetNames = serviceDocument.getEntitySetNames();
Map<String, URI> entitySets = serviceDocument.getEntitySets();
Map<String, URI> singletons = serviceDocument.getSingletons();
Map<String, URI> functionImports = serviceDocument.getFunctionImports();
URI productsUri = serviceDocument.getEntitySetURI("Cars");
What is wrong with my implementation?
That's because the service document's Content-Type is application/xml, not the "application/json;odata.metadata=full". maybe you should add the header "Accept"

How to set a faultCode in a SOAPFault?

Why can I set a faulString, but can't I set a custom fault code in a SOAPFault? When I throw the exception, the text "Code X" does not appear in the SoapFaultException. Someone could tell me why? Thanks.
SOAPFault soapFault = SOAPFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL).createFault();
soapFault.setFaultString("String Y")
soapFault.setFaultCode("Code X");
throw new SOAPFaultException(soapFault);
It is possible to get the fault code in the soap response with the following example:
String faultString = "String Y";
String faultCodeValue = "Code X";
QName faultCode = new QName("nameSpaceURI", faultCodeValue);
SOAPFault soapFault = null;
try {
soapFault = SOAPFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL).createFault(faultString, faultCode);
throw new javax.xml.ws.soap.SOAPFaultException(soapFault);
} catch (SOAPException e1) {
//
}
I get the following soap fault back:
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope" xmlns="">
<faultcode xmlns:ns0="nameSpaceURI">ns0:Code X</faultcode>
<faultstring>String Y</faultstring>
</S:Fault>
</S:Body>
</S:Envelope>
From documentation:
Fault codes, which given information about the fault, are defined in
the SOAP 1.1 specification. This element is mandatory in SOAP 1.1.
Because the fault code is required to be a QName it is preferable to
use the setFaultCode(Name) form of this method.
faultCode - a String giving the fault code to be set. It must be of
the form "prefix:localName" where the prefix has been defined in a
namespace declaration.
Notice that the fault code your're setting has to be this format: prefix:localName. You're setting: Code X, that is why you do not see it. Use this method and all should be OK.

Categories