Question

I am trying to do a simple SOAP webserver with Clojure and jax-ws

(ns test-ws.routes.home
(:import (javax.jws WebMethod WebService)
       (javax.xml.ws Endpoint)))

(defprotocol Calculator (add [this a b]))

(deftype ^{WebService {:targetNamespace "test.seltzer" }}
     CalcWeb [] Calculator (^{WebMethod []} add [this a b] (+ a b)))

(def endpoint (Endpoint/publish "http://localhost:8080/calcWeb" (CalcWeb.)))

After that WSDL is available at http://localhost:8080/calcWeb?wsdl but when I am trying to call it from SOAP-UI I got: com.sun.org.apache.xerces.internal.dom.ElementNSImpl cannot be cast to java.lang.Number

My idea was that clojure cannot map SOAP request to number so I added annotation

(defprotocol Calculator (add [this ^Integer a ^Integer b]))
(deftype ^{WebService {:targetNamespace "test.seltzer" }}
     CalcWeb [] Calculator (^{WebMethod []} add [this ^Integer a ^Integer b] (+ a b)))

Now on compile time I have the following error: Can't find matching method: add, leave off hints for auto match.

I also tried this

(defprotocol Calculator (add [this ^Integer a ^Integer b]))

(deftype ^{WebService {:targetNamespace "test-ws.routes.home"}}
     CalcWeb [] Calculator (^{WebMethod []} add [this
                               #^{WebParam {:name "param0"} :tag Integer} a
                               #^{WebParam {:name "param1"} :tag Integer} b] (+ a b)))

I gave me same error.

Am I missing something ?

Was it helpful?

Solution

I really was close to solve the problem. The trick was to use interface instead of protocol. I hope that this will be useful for some one:

(ns wstest.core
  (:import (javax.jws WebMethod WebService WebParam)
       (javax.xml.ws Endpoint)
       (wstest.java Person)))

(definterface IFooService
  (^int add [^int a ^int b])
  (^String sayHi [^String name])
  (^wstest.java.Person makePerson [^String firstName ^String lastName])
  (^String sayHiTo [^wstest.java.Person person]))

(deftype ^{WebService {:targetNamespace "o.m.g"}} FooService []
  IFooService
  (^int ^{WebMethod []} add [this ^int #^{WebParam {:name "a"}} a ^int #^{WebParam {:name "b"}} b]
    (int (+ a b)))
  (^String ^{WebMethod []} sayHi [this ^String #^{WebParam {:name "name"}} name]
    (str "Hello, " name "!"))
  (^wstest.java.Person ^{WebMethod []} makePerson [this ^String #^{WebParam {:name "firstName"}} firstName ^String #^{WebParam {:name "lastName"}} lastName]
    (doto (wstest.java.Person.)
      (.setFirstName firstName)
      (.setLastName lastName)))
  (^String ^{WebMethod []} sayHiTo [this ^wstest.java.Person #^{WebParam {:name "person"}} person]
    (str "Hello, " (.getFirstName person) " " (.getLastName person) "!")))

(def endpoint (atom nil))

(do
  (if-not (nil? @endpoint)
    (.stop @endpoint))
  (reset! endpoint (Endpoint/publish "http://localhost:8080/fooService" (FooService.))))

Person.java:

package wstest.java;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
 @XmlType(name = "Person")
 public class Person {
@XmlElement
protected String firstName;
@XmlElement
protected String lastName;

public String getFirstName() {
    return firstName;
}

public void setFirstName(String value) {
    this.firstName = value;
}

public String getLastName() {
    return lastName;
}

public void setLastName(String value) {
    this.lastName = value;
}
}

OTHER TIPS

Looks like you were using my code in the example from Japila's blog. I've posted my full source with directions:

https://gist.github.com/seltzer1717/f67e77bb5b47d08612fd7f636832a4ff

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top