Delete rest with parameters - java

I need to write this REST request in java using Httpdelete or any other library.
curl -X DELETE -d '{"ruleid":"1" }' http://192.168.1.1:8080/wm/acl/rules/json
I couldn't find a way to parse the Json data !
Thanks for your help !

Like others said, it is unusual that a DELETE request contains a body. But it is not strictly impossible as long as the server supports it.
There are many ways to build a REST Client in Java (see https://stackoverflow.com/a/5024571/1018443). A common way is to use Jersey 2.
In Jersey 2, the .delete() method does not contain a parameter for the body entity. But you can use .build to create a DELETE request with a body. Here is an example:
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
public class RestClient {
public static void main(String[] args) {
Model model = new Model();
ClientConfig config = new ClientConfig();
config.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
Client client = ClientBuilder.newClient(config);
WebTarget target = client.target("http://192.168.1.1:8080/");
String response = target
.path("wm/acl/rules/json")
.request(MediaType.APPLICATION_JSON)
.build("DELETE", Entity.entity(model, MediaType.APPLICATION_JSON))
.invoke(String.class);
System.out.println(response);
}
private static class Model {
public int ruleid = 1;
}
}
Note that you need to configure the client with Property ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION = true. Otherwise you get an Exception: Entity must be null for http method DELETE.
You will find many examples on how to build a Java REST client with Jersey. For example: https://howtodoinjava.com/jersey/jersey-restful-client-examples/

You have to use POST request instead of DELETE, because body of DELETE request is ignored.
From spec:
The DELETE method requests that the origin server delete the resource identified by the Request-URI
reference link

Related

How to set Content-Type Header in Java MicroProfile RestClient during method call

I am currently using the Java MicroProfile RestClient and have following problem:
Backend provides an api to receive binary files
Backend would be happy to receive a Content-Type header containing the Mime-Type of the binary file
I am not able to set Content-Type per method parameter
I have following code on client-side:
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.smallrye.mutiny.Uni;
#RegisterRestClient
public interface RestClient {
#POST
#Path("/api/path/v1")
Uni<String> createResource(#HeaderParam("Content-Type") String contentType, byte[] body);
}
The #HeaderParam("Content-Type") will always be overwritten with "application/json".
If I set the #Consumes Property the Content-Type would always be the same but I want to set it during the method call. (byte[] could contain image, video, text ...)
Has anyone an idea how I could archive this?
May there is a better option instead of using a simple byte[] as body?
Best thanks!
Maybe you could try the solution mentioned here: https://quarkus.io/guides/rest-client#custom-headers-support

How to add a body to a HTTP request using Java Spring's RestTemplate's exchange method?

I am trying to send a HTTP request using RestTemplate's exchange method. However, for some reason the HTTP body of the sent request seems to be empty.
Here is the code I currently have (the original code is more complex):
package somepackage;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.client.RestTemplate;
public class SomeMainClass {
public static void main(String[] args) {
HttpEntity<String> entity = new HttpEntity<>("body contents", new HttpHeaders());
new RestTemplate().exchange("http://localhost:5678/someRequest", HttpMethod.GET, entity, String.class);
}
}
In order to confirm whether the code above worked, I ran nc -l 5678 (which listens for a request on port 5678) in a terminal, and in my IDE, I ran the above code. The nc command in my terminal printed out a HTTP request that does not have a body (I expected it to have a body with the string "body contents").
Why doesn't this work? How can I fix it?
Note: Here are the requirements that made me decide to use the exchange method
It has to be a GET request.
The request needs to have a body.
I have to set some headers.
I need to read the body of the response.
GET methods don't have body. You might want to change HttpMethod.GET to HttpMethod.POST.
If you want to supply parameters in GET, you can change the URL to something like http://localhost:5678/someRequest?expiry=23000.
More details at Spring RestTemplate GET with parameters.

Java SOAP client using SOAP UI library and WSDL file

I'm trying to build a Java based SOAP client which imports a WSDL file and sends a request to the end point specified in the WSDL. I'm currently using the SOAP UI library and while it can compile, it is connecting to the wrong endpoint. In addition, I'm not sure where/how I define the authentication credentials (user/pass).
I am using a base code found on this site but this doesn't include authentication. It is also getting the endpoint from the wrong attribute when I run the code. Please help!
package com.bbog.soap;
import com.eviware.soapui.impl.wsdl.WsdlInterface;
import com.eviware.soapui.impl.wsdl.WsdlOperation;
import com.eviware.soapui.impl.wsdl.WsdlProject;
import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlImporter;
import com.eviware.soapui.model.iface.Operation;
public class WsdlAnalyzer {
public static void main(String[] args) throws Exception {
WsdlProject project = new WsdlProject();
WsdlInterface[] wsdls = WsdlImporter.importWsdl(project, "file:/home/asarkar/Documents/EthocaAlerts-Sandbox.wsdl");
WsdlInterface wsdl = wsdls[0];
for (Operation operation : wsdl.getOperationList()) {
WsdlOperation op = (WsdlOperation) operation;
System.out.println("OP:"+op.getName());
System.out.println(op.createRequest(true));
System.out.println("Response:");
System.out.println(op.createResponse(true));
}
}
}

Unable to override a response header using a Jersey client filter

I am trying to use the Jersey client API to consume a third-party REST service. I plan to use the automatic POJO deserialisation to go from JSON responses to Java objects.
Unfortunately, the third party service returns the responses using the content type "text/javascript". My Jersey client fails to understand that this should be considered as a JSON object and fails to deserialise the object.
I wrote a simple Jersey server application to verify that by changing the content type from "text/javascript" to "application/json" that the deserialisation works.
Armed with this information, I set about to use a Jersey client filter to modify the response headers. The code comes from a comment by the author of this question. In fact, the question appears to be exactly the same as mine - however the answerer mis-answered the question and shows how to modify the request headers (rather than the response headers). The original author was able to use the answer to create his solution, but, it seems his stated solution fails to work.
The filter code is:
client.addFilter(new ClientFilter() {
#Override public ClientResponse handle(ClientRequest cr)
throws ClientHandlerException {
ClientResponse response = getNext().handle(cr);
response.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
return response;
}
});
When executed however, an UnsupportedOperationException is raised:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.clear(Collections.java:1035)
at com.sun.jersey.core.util.StringKeyIgnoreCaseMultivaluedMap.putSingle(StringKeyIgnoreCaseMultivaluedMap.java:78)
at com.sun.jersey.core.util.StringKeyIgnoreCaseMultivaluedMap.putSingle(StringKeyIgnoreCaseMultivaluedMap.java:56)
at App$1.handle(App.java:49)
at com.sun.jersey.api.client.Client.handle(Client.java:648)
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:680)
at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:507)
at App.main(App.java:63)
The returned headers appear to be wrapped in an unmodifiable collection.
I then attempted to copy all of the headers to a new collection, but there is no way that I can see to set a map of headers back into the response.
Finally, I thought perhaps I can create a new ClientResponse containing my amended headers. However, the constructor for ClientResponse has this signature:
public ClientResponse(int status,
InBoundHeaders headers,
InputStream entity,
MessageBodyWorkers workers)
It is trivial to copy the status, headers and entity variables from the original. However, I can see no way of getting a reference to the workers field.
How can I use a Jersey client filter to modify the response header from "text/javascript" to "application/json" so that my POJO deserialisation will work?
In Jersey 2, register an implementation of a ClientResponseFilter with the ClientConfig in order to manipulate the HTTP headers of incoming responses.
For example, this seems to work well with Jersey 2.3.1 for manipulating HTTP header:
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.client.ClientRequestContext;
import org.glassfish.jersey.client.ClientConfig;
/* Ensure that there is an "application/xml" Content-Type header on
* successful responses without a content type header. */
#Provider
public static class EnsureXmlContentTypeFilter implements ClientResponseFilter {
#Override
public void filter(ClientRequestContext requestContext,
ClientResponseContext responseContext) {
if (200 == responseContext.getStatus() &&
null == responseContext.getHeaderString(HttpHeaders.CONTENT_TYPE)) {
responseContext.getHeaders().add(
HttpHeaders.CONTENT_TYPE, "application/xml"
);
}
}
}
private final ClientConfig config = new ClientConfig()
// Registering this filter adds a "Content-Type: application/xml"
// header to each response that lacks Content-Type headers.
.register(EnsureXmlContentTypeFilter.class)
;
private final Client client = ClientBuilder.newClient(config);
The Jersey documentation on Filters and Interceptors isn't perfect, but it does have some links to the javadocs for the relevant classes: https://jersey.java.net/documentation/latest/filters-and-interceptors.html
I am getting XML responses from a service which responds with XML content, but lacks a "Content-Type: application/xml" header. Probably a better approach would be to register MessageBodyReaders, but the above approach works while I'm playing around with that service's API.
I don't have an answer to your real question, but I think I see how you can get that workers instance if you want to try to create a new response in your filter.
The "workers" object that you need appears to be a singleton. If you can get hold of your com.sun.jersey.api.client.Client instance, you can retrieve the workers object. In my case, the Jersey client code is in a unit test which subclassed JerseyTest. JerseyTest defines a method "client()" which returns the Client object. I added the following test code (well not exactly but close):
MessageBodyWorkers workers = client().getMessageBodyWorkers();
Then I set a breakpoint in the constructor of ClientResponse (this is the original ClientResponse returned by Jersey. I have not attempted to clone it because I don't need to for my test). The workers passed to the constructor was the same instance. So, even though you can not get the workers object from the response object, you should be able to get it elsewhere.
Guido's answer provides the insight required to create a new ClientResponse object and return it instead. For reasons that I've not yet bothered to track down, creating a new InboundHeaders, adding all the existing headers to it, and then modifying the single header in question still fails with an UnsupportedOperationException. As such, to re-write the headers, we iterate over the original headers and build the correct set iteratively:
final Client client = Client.create(clientConfig);
client.addFilter(new ClientFilter()
{
#Override
public ClientResponse handle(ClientRequest cr) throws ClientHandlerException
{
final ClientResponse response = getNext().handle(cr);
final InBoundHeaders headers = new InBoundHeaders();
for (String header : response.getHeaders().keySet())
{
if (header.equals(HttpHeaders.CONTENT_TYPE))
{
headers.putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
}
else
{
headers.put(header, headers.get(header));
}
}
return new ClientResponse(response.getStatus(),
headers,
response.getEntityInputStream(),
client.getMessageBodyWorkers());
}
}
In Jersey 2, you should use a ClientResponseFilter. Then you can just call responseContext.getHeaders().putSingle(...).
Under Java 8 you can do it with a lambda:
client.register((ClientResponseFilter) (requestContext, responseContext) ->
responseContext.getHeaders().putSingle("Content-Type", "application/json"));
If you want to re-use an existing filter instance, just register it on the Client instead of on the ClientConfig.
Old way (Jersey-1.9):
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
Client client = new Client();
client.addFilter(new HTTPBasicAuthFilter(username, password));
New way (Jersey-2.3):
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import org.glassfish.jersey.client.filter.HttpBasicAuthFilter;
Client client = ClientBuilder.newClient();
client.register(new HttpBasicAuthFilter(username, password));
That's not the best solution, but it may help you to migrate.

How do I get the Source IP of a SOAP requesting client machine?

how do you get source ip, username, password, etc... of the client machine that sends a soap request? is there any of these details that one can pull for logging purposes?
I am using Java to handle the incoming SOAP requests. The service simply adds 2 numbers and is working, but I just need to get some client details.
Thanks, Lavanya
If you're using JAX-WS, inject a WebServiceContext like so:
import javax.annotation.Resource
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
#WebService()
public class Test
{
#Resource WebServiceContext context;
#WebMethod(operationName = "getInfo")
public String getInfo()
{
HttpServletRequest request = (HttpServletRequest)context.getMessageContext().get(MessageContext.SERVLET_REQUEST);
return "IP: "+request.getRemoteAddr()+", Port: "+request.getRemotePort()+", Host: "+request.getRemoteHost();
}
}
Will return something like:
IP: 127.0.0.1, Port: 2636, Host: localhost
Look at the API for the rest of the methods. Basically, once you have your HttpServletRequest object, the rest is pretty easy.
I have figured the solution like below -
#Endpoint
public class DataEndpoints {
....
....
private HttpServletRequest httpServletRequest;
#Autowired
public void setRequest(HttpServletRequest request) {
this.httpServletRequest = request;
}
#PayloadRoot(namespace = employeeNS, localPart = "syncRelation")
#ResponsePayload
public SyncRelationResponse dataSync(#RequestPayload SyncOrderRelation request) {
String incoming = "IP Address -> " + this.httpServletRequest.getRemoteAddr();
}
}
By using the following method, I can directly access HttpServletRequest. And then I can access all data i need.
I hope it will help someone in this context.
I am not surte I fully understand your idea of getting username and password of client machine.
In general with Soap look at Soap Header, they are supposed to carry the authentication information (which could be username, password or some kind of security toke).
For the IP, your Soap is coming over Http and therefore when you receive your request you can try and look at your Http headers to see what information it gives you. Though I have never tried to get the IP of the client from it, but it might be there in the HTTP header
What soap stack are u using. If u deployed it as a war file using axis it is pretty easy to do it. u need to get hold of the httprequestobject and call the HTTPServletRequest.getRemoteAddr() method on it.

Categories