Further to IRC conversations:
I'm attempting to generate a JAX-WS service using Clojure. The main
stumbling block was annotations; that's been removed, so I gave it a
shot using deftype.
My first strike works code-wise, so I sent it to the list earlier today.
When it comes to actually integrating the output into the Java world,
though, things get hairy. JAX-WS has a bunch of demands on classes in
order for its tools (such as wsgen) to accept them:
<http://java.sun.com/webservices/docs/2.0/tutorial/doc/JAXWS3.html>
---
JAX-WS endpoints must follow these requirements:
* The implementing class must be annotated with either the
javax.jws.WebService or javax.jws.WebServiceProvider annotation.
* The implementing class may explicitly reference an SEI through the
endpointInterface element of the @WebService annotation, but is not
required to do so. If no endpointInterface is not specified in
@WebService, an SEI is implicitly defined for the implementing class.
* The business methods of the implementing class must be public, and
must not be declared static or final.
* Business methods that are exposed to web service clients must be
annotated with javax.jws.WebMethod.
* Business methods that are exposed to web service clients must have
JAX-B-compatible parameters and return types. See Default Data Type
Bindings.
* The implementing class must not be declared final and must not be
abstract.
* The implementing class must have a default public constructor.
* The implementing class must not define the finalize method.
* The implementing class may use the javax.annotation.PostConstruct or
javax.annotation.PreDestroy annotations on its methods for lifecycle
event callbacks.
The @PostConstruct method is called by the container before the
implementing class begins responding to web service clients.
The @PreDestroy method is called by the container before the endpoint
is removed from operation.
---
The classes generated by deftype are final; the javap output is
---
public final class com.example.FooBarService extends java.lang.Object
implements com.example.FooBarInterface{
public static {};
public com.example.FooBarService();
public java.lang.String createCustomer(java.lang.String,
java.lang.String, java.lang.String);
}
---
That doesn't make JAX-WS's tools happy:
---
com.sun.tools.ws.processor.modeler.ModelerException: modeler error:
Classes annotated with @javax.jws.WebService must not be final.
---
Digging into the compiler, it looks like individual fields can be made
non-final by flagging them as mutable. The class emitter in `compile`,
however, always passes ACC_PUBLIC + ACC_SUPER + ACC_FINAL to the
ClassVisitor.visit method... so classes produced in this way are
always final.
From a purity perspective, this is nice: Clojure prohibits
implementation inheritance because it's a Bad Idea®. However, this
hampers interop (I don't *want* to do implementation inheritance, but
JAX-WS demands non-final classes!), and the mutable/volatile options
for fields seem to suggest that getting hands dirty is acceptable at
the level of deftype… and thus having some optional way to produce non-
final classes might be a reasonable feature to add.
Chouser suggested gen-class, which generates non-final classes; that's
my next fallback, once annotation support for gen-class gets
integrated. However, if this isn't an intentional and inflexible
limitation on deftype, I thought I'd investigate removing it. So I
spent a little time with the compiler, producing three patches:
* Pass options through to deftype emission (they never made it
past deftype in the current code).
* Propagate class accessibility flags throughout build/compile
(parameterizing the ACC_FINAL/ACC_PUBLIC/ACC_SUPER flags).
* Allow (and check for) :non-final as a boolean option for deftype.
The test suite runs without problems, and I've verified that adding
`:non-final true` generates a non-final class (and the reverse). With
this change I'm able to run wsgen against a jar built by Leiningen,
containing no Java code, and get WSDL as output. Pretty neat, no?
I've pushed these to my GitHub fork (rather than sending patches to
the list):
<http://github.com/rnewman/clojure/tree/deftype-non-final>
Opinions, thoughts, critiques, "you're insane"s, etc. welcome.
Thanks,
-Richard
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en