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));
}
}
}
Related
I have a simple micronaut app.
I have two separate endpoints where the method that executes will call an API using a client (I've tried both the http client from "java.net.http.HttpClient" and "io.micronaut.http.client.RxHttpClient" but the same issue happens).
When you hit any of the endpoints after starting the app, the function will execute as expected, where the client calls an external API and retrieves the response as a string. If you try to hit that same endpoint again, it will throw:
"javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure."
I don't think this is an issue on the API's server side for the following reasons:
This issue happens when I hit two separate endpoints with two separate external APIs
The request goes through the first time no problem
I can hit the same APIs in postman without error - it's just when I call them with the client that there is an issue.
My controller:
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.HttpResponse;
import javax.inject.Inject;
import java.io.IOException;
import static io.micronaut.http.HttpRequest.GET;
#Controller("/api")
public class DeckController {
#Inject
private DeckService deckService;
#Get(value = "/drawRx")
public HttpResponse<Card> drawCardRx(){
deckService.drawCardRx("ijhhxvxwn63g",1);
return HttpResponse.ok();
}
}
One of my services where the client calls the API:
public void drawCardRx(String deckId, int amount){
final String newDeckUrl = "/deck/"+deckId+"/draw/?count="+amount;
Disposable result = this.httpClient
.retrieve( GET(newDeckUrl))
.subscribe(data -> System.out.println(data));
return;
}
Like I said, the first time I hit the endpoint, the response is returned from the server without a problem.
I've tried the below articles and followed those steps, but no improvement.
https://www.baeldung.com/java-ssl-handshake-failures
How to solve javax.net.ssl.SSLHandshakeException Error?
Is there something I am missing?
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
I don't if this is even possible, which is why I thought I'd ask.
I forgot to mention I'm using Jersey 1.19 and Java 1.6.
I created a RESTful web service in Java using the Jersey API, as well as client code to call the web service. The client code is Jersey-based, as well. The problem I'm running into is I don't want to deploy the JAR file to the web server every time I make a change and want to test -- the web server is on a remote server and I"m coding on a local computer.
Is it possible to simulate a client-server web service call completely within the IDE (i.e. Eclipse)? In other words, I want to call the web service from my
local computer, without having to host it on a web server; no different than
calling a function.
Here is the client code:
package com.xyzcorp.webservices;
import javax.ws.rs.core.MediaType;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
public class RestClient {
public static void main(String[] args) {
Client client = Client.create();
/*
Right now, it's calling the web service on the web server.
I want to call this same web service but from within the code local
to my computer, without hosting it on a web server.
*/
WebResource webResource = client.resource("http://myserver.com/rest/ids/12345");
ClientResponse response = webResource.accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}
}
}
Here is the web service code:
package com.xyzcorp.webservices;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.xyzcorp.webservices.EmpData;
#Path("/rest")
public class RestWebService {
#GET
#Path("/ids/{ids}")
#Produces(MediaType.APPLICATION_JSON)
public EmpData getEmpDataJSON(
#PathParam("ids") String ids)
...
return empData;
}
}
Is it possible to call the RestWebService class directly without having to use a web server? I.e. `WebResource webResource = client.resource(new RestWebService().EmpData("12345"));
Thank you very much.
Use Jersey Test Framework. Run (semi) Integration/Unit tests on your resources like you would a normal unit test. For example
public class MainTest extends JerseyTest {
public MainTest() throws Exception {
super("com.sun.jersey.samples.helloworld.resources");
}
#Test
public void testHelloWorld() {
WebResource webResource = resource();
String responseMsg = webResource.path("helloworld").get(String.class);
assertEquals("Hello World", responseMsg);
}
}
The JerseyTest will start and stop an embedded server for each test case. It could even be an in memory server (so as not to take so much load time) depending on what server dependency you want to use. Here's an example dependency
<dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId>
<artifactId>jersey-test-framework-grizzly2</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
The link I provided shows other dependencies you can use.
Here is another example usage (the bottom part is for Jersey 1.x - the top is 2.x)
This might be of use to you:
http://www.eclipse.org/webtools/community/education/web/t320/Implementing_a_Simple_Web_Service.pdf
particularly page 12 onwards.
Hope it helps.
EDIT : just in case, your machine URL will contain "localhost" for services running on your local computer.
I am trying to access web services that are defined in WSDL by giving the url of the WSDL. The specific case I am working on is the ebay "FindingService".
After parsing the WSDL, I search for the service I am looking for (for example "FindingService"). Next, I want to be able to use that service (send keywords and get results) through some sort of client. I looked around and found the following code that I tried to modify to use it for my example. Since I am still new to WSDL, I am not sure of how to adapt it and I keep getting the error: Undefined port type: {http://WSDL/}face
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
public class client{
public static void main(String[] args) throws Exception {
URL url = new URL("http://developer.ebay.com/webservices/finding/latest/findingservice.wsdl");
//1st argument service URI, refer to wsdl document above
//2nd argument is service name, refer to wsdl document above
QName qname = new QName("http://www.ebay.com/marketplace/search/v1/services", "FindingService");
Service service = Service.create(url, qname);
face hello = service.getPort(face.class);
System.out.println(hello.getHelloWorldAsString("test"));
}
}
the second class is:
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
//Service Endpoint Interface
#WebService
#SOAPBinding(style = Style.RPC)
public interface face{
#WebMethod String getHelloWorldAsString(String name);
}
the third class is:
import javax.jws.WebService;
//Service Implementation
#WebService(endpointInterface = "face")
public class endp implements face{
#Override
public String getHelloWorldAsString(String name) {
return "Hello World JAX-WS " + name;
}
}
I'd be thankful if I can get some guidance. Is it possible to access services like that or do I have to use the ebay API (with keys etc..) ?
WSDL is just a contract between the client and the server.
The best solution is not parse the WSDL in runtime and try to call the actions. You probably want to call these actions to do something useful. Ex: find all user Ebay orders.
Each of these actions can have complex inputs and outputs. The best solution to work with SOAP webservices in Java is usually generate code based in the WSDL, so you will have a full working client without too much work.
I can recommend these APIs:
JAX-WS:
http://www.mkyong.com/webservices/jax-ws/jax-ws-wsimport-tool-example/
Spring-WS:
https://spring.io/guides/gs/consuming-web-service/
Axis 2:
https://axis.apache.org/axis2/java/core/docs/userguide-creatingclients.html
I have the task of creating a web service that takes requests from multiple clients. I am new to web services so i used this tutorial:
http://www.java-forums.org/blogs/web-service/1145-how-create-java-web-service.html
This is exactly what i am looking for. A web service with no java ee.
It is preferable that is stick with java se, it's a policy that is prefered to be kept.
Now i would like to go one step further and implement the service so that it processes requests from multiple clients that operate on a shared resource.
Ideally i would like something like this:
Client client = new Client();
client.processRequest(string);
And the web service will process the requests in the order they arrive. The requests will come in as an request is processed so it will be kept in a stack.
The problem is i just on't know how to send the response back to the specific client. The response will be a string. The only thing i came up with, at least in principle, is to send a object that remembers where it came from but that just seems the web services job.
I have searched the internet but did not find a solution.
If possible using only SE please help.
If you think it is not possible without EE you can say so, but i would very much like an answer using only SE
I think what you are trying to implement is an Asynchronous Webservice. The following link tells you how to implement it in Java SE.
http://java.dzone.com/articles/asynchronous-java-se-web
You can do this using the Endpoint.publish methods in Java SE. First, you create a simple "endpoint interface":
package com.example;
import javax.jws.WebService;
#WebService
public interface ExampleService {
String getDateTime();
}
Then you specify that interface in an implementation class. As you can see, both classes must be annotated with #WebService.
package com.example;
import java.io.IOException;
import java.net.URL;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
import javax.xml.ws.Service;
import javax.xml.namespace.QName;
#WebService(endpointInterface = "com.example.ExampleService",
serviceName = "ExampleService",
portName = "timeService",
targetNamespace = "http://example.com/time")
public class ExampleServiceImpl
implements ExampleService {
public String getDateTime() {
return String.format("%tc", System.currentTimeMillis());
}
public static void main(String[] args)
throws IOException {
// Create server
Endpoint endpoint =
Endpoint.publish("http://localhost:8080/example",
new ExampleServiceImpl());
URL wsdl = new URL("http://localhost:8080/example?wsdl");
// Create client
Service service = Service.create(wsdl,
new QName("http://example.com/time", "ExampleService"));
ExampleService e = service.getPort(ExampleService.class);
// Test it out
System.out.println(e.getDateTime());
endpoint.stop();
}
}
By default, JAX-WS will treat all public methods of an endpoint interface as web methods (since that is commonly what developers will want). You can have more control by placing the #WebMethod annotation on only the methods you want exposed as web services.
See the JAX-WS specification for all the details.