Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JAX-WS Generating code with lower case operations with breaks WSDL compliance #2

Closed
zebity opened this issue Jan 3, 2023 · 3 comments

Comments

@zebity
Copy link
Owner

zebity commented Jan 3, 2023

Issues:

ONVIF WSDL specifies all operation starting with upper case letters:

Example:

                <wsdl:operation name="GetDeviceInformation">
                        <wsdl:documentation>This operation gets basic device information from the device.</wsdl:documentation>
                        <wsdl:input message="tds:GetDeviceInformationRequest"/>
                        <wsdl:output message="tds:GetDeviceInformationResponse"/>
                </wsdl:operation>

But JAX-WS converts these to lower case first letter ie "getDeviceInformation"

This means that the message interface is no longer conformant with WSDL.

Can this be disabled ?

Testing:

via curl

curl --verbose http://127.0.0.1:9080/onvif/device_service -H "Content-Type: text/xml" --data '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><getDeviceInformation xmlns="http://www.onvif.org/ver10"></getDeviceInformation></s:Body></s:Envelope>'

Works.

curl --verbose http://127.0.0.1:9080/onvif/device_service -H "Content-Type: text/xml" --data '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><GetDeviceInformation xmlns="http://www.onvif.org/ver10/device/wsdl"></GetDeviceInformation></s:Body></s:Envelope>'

Fails

@zebity
Copy link
Owner Author

zebity commented Jan 16, 2023

Build WsImport and run via debugger. Tracing this it is apparent that the "name mangling" of identifiers doe not seem to allow for maintaining WSDL compliance. Tracing wsdl based generation here is where name mangling occurs:

	NameConverter$Standard(NameUtil).toMixedCaseName(List<String>, boolean) line: 209	
	NameConverter$Standard.toVariableName(String) line: 95	
	BindingHelper.mangleNameToVariableName(String) line: 47	
	Operation.getJavaMethodName() line: 215	
	WSDLModeler.getJavaNameForOperation(Operation) line: 2777	
	WSDLModeler.createJavaMethodForOperation(Port, Operation, JavaInterface) line: 2413	
	WSDLModeler.createJavaInterfaceForPort(Port, boolean) line: 2302	
	WSDLModeler.processPort(Port, Service, WSDLDocument) line: 462	
	WSDLModeler.processService(Service, Model, WSDLDocument) line: 226	
	WSDLModeler.internalBuildModel(WSDLDocument) line: 197	
	WSDLModeler.buildModel() line: 111	
	WsimportTool.buildWsdlModel(WsimportTool$Listener, WsimportTool$Receiver) line: 413	
	WsimportTool.run(String[], WsimportTool$Listener, WsimportTool$Receiver) line: 180	
	WsimportTool.run(String[]) line: 158	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43	
	Method.invoke(Object, Object...) line: 566	
	Invoker.invoke(String, String[]) line: 132	
	WsImport.main(String[]) line: 29

This code is part of Jakarta JAX-WS (Metro) reference implementation: https://github.com/eclipse-ee4j/metro-jax-ws

Need to determine if this is Jakarta defect.

@zebity
Copy link
Owner Author

zebity commented Jan 19, 2023

Careful reading of Jakarta JAX-WS specification:

Conformance (Operation naming): In the absence of customizations, the value of the name attribute of the wsdl:operation element MUST be the name of the Java method. The jakarta.jws.WebMethod (see Section 7.11.2, “jakarta.jws.WebMethod”) annotation MAY be used to customize the value of the name attribute of the wsdl:operation element and MUST be used to resolve naming conflicts. If the exclude element of the jakarta.jws.WebMethod is set to true then the Java method MUST NOT be present in the wsdl as a wsdl:operation element.

Make it clear that "value of name" does not mean "verbatim" equality and that without customisation, Java can still apply its "naming convention" is applied:

2.8. XML Names - Appendix D of Jakarta XML Binding[39] defines a mapping from XML names to Java identifiers. Jakarta XML Web Services uses this mapping to convert WSDL identifiers to Java identifiers with the following modifications and additions:

Method identifiers - When mapping wsdl:operation names to Java method identifiers, the get or set prefix is not added. Instead the first word in the word-list has its first character converted to lower case.

To to remove Java naming on methods required XML Binding customisation. There are three ways to achieve this:

  1. Post Process generated Java code to change the case to it is consistent with WSDL
  2. Use official XML Binding Customisation (xml script which is either included inline with WSDL or via wsimport -b flag
  3. Hack the WsImport generator

I have done (3) and created a utility script to read WSDL and generate (2).

(3) is tested for Jakarta but fails for Javax, (2) needs testing but should work for both JAX & JAK.

See hacked metro fork for (3) and src/main/xml for xslt script for (2).

Closing issue,

@zebity
Copy link
Owner Author

zebity commented Jan 19, 2023

This is not bug but "correct by specification" behaviour.
Two workarounds are available (see comment above).

@zebity zebity closed this as completed Jan 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant