[
https://issues.apache.org/jira/browse/CXF-4016?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Daniel Kulp reassigned CXF-4016:
--------------------------------
Assignee: Daniel Kulp
> JAX-WS schema generation of an Exception annoted with @WebFault that contains
> a property of a class annotated with @XmlRootElement causes the schema of the
> WSDL to generate the incorrectly
> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CXF-4016
> URL: https://issues.apache.org/jira/browse/CXF-4016
> Project: CXF
> Issue Type: Bug
> Components: JAX-WS Runtime
> Affects Versions: 2.4
> Reporter: Vincent Furlanetto
> Assignee: Daniel Kulp
>
> I have the following Exception Class (BusinessException) that is annotated
> with @WebFault. BusinessException has a property named exceptionMessage that
> is of Type ExceptionMessage. ExceptionMessage is annotated with the
> @XmlRootElement annotation.
> When CXF generates the WSDL via hitting the web wervice URL it generates a
> schema with an invalid element for the BusinessException element.
> See the schema in question here:
> {code}
> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
> targetNamespace="http://www.mycompany.com/platform/exception"
> xmlns:tns="http://www.mycompany.com/platform/exception"
> xmlns:xs="http://www.w3.org/2001/XMLSchema">
> <xs:element name="ExceptionMessage" type="tns:exceptionMessage"/>
> <xs:complexType name="exceptionMessage">
> <xs:sequence>
> <xs:element minOccurs="0" name="classCause" type="xs:string"/>
> <xs:element minOccurs="0" name="severity" type="xs:string"/>
> <xs:element minOccurs="0" name="exceptionMessage" type="xs:string"/>
> <xs:element minOccurs="0" name="displayMessage" type="xs:string"/>
> <xs:element name="code" type="xs:int"/>
> <xs:element minOccurs="0" name="informationCode" type="xs:string"/>
> <xs:element minOccurs="0" name="uniqueID" type="xs:string"/>
> <xs:element minOccurs="0" name="userResolution" type="xs:string"/>
> <xs:element minOccurs="0" name="exceptionCause" type="xs:string"/>
> <xs:element minOccurs="0" name="stack" type="xs:string"/>
> </xs:sequence>
> </xs:complexType>
> <xs:complexType name="BusinessException">
> <xs:sequence>
> <xs:element nillable="true"/>
> </xs:sequence>
> </xs:complexType>
> <xs:element name="BusinessException" type="tns:BusinessException"/>
> </xs:schema>
> {code}
> Notice this portion of the schema here:
> {code}
> <xs:complexType name="BusinessException">
> <xs:sequence>
> <xs:element nillable="true"/>
> </xs:sequence>
> </xs:complexType>
> {code}
> It is generating an invalid schema element "<xs:element nillable="true"/>"
> without a name or ref.
> The problem appears to be with the fact that the ExceptionMessage class is
> annotated with @XmlRootElement. If I remove the @XmlRootElement from the
> ExceptionMessage class it all works fine. My problem is that the
> ExceptionMessage class is also used by other services in my code that need to
> serialize the ExceptionMessage to xml via JAXB. And as I'm sure you already
> know when using the JaxbContext will throw an Exception if the class is not
> annotated with the @XmlRootElement. I have been able to work around this
> issue by simply removing the @XmlRootElement annotation and programmatically
> implementing a JAXBElement object which will then allow me to use the
> JaxbContext without getting the non present @XmlRootElement Exception.
> {code}
> QName qName = new QName("http://www.mycompany.com/platform/exception",
> "ExceptionMessage");
> JAXBElement<ExceptionMessage> jaxbElement = new
> JAXBElement<ExceptionMessage>(qName, ExceptionMessage.class,
> exceptionMessageObj);
> {code}
> So I guess what I'm asking is isn't it possible just use the simple class
> name for the WSDL schema name for a class that is annotated with
> @XmlRootElement verus generating an invalid schema element without a name or
> ref?
> Please see the code example below:
> {code}
> package com.mycompany.platform.exception.checked;
> import java.io.Serializable;
> import javax.xml.ws.WebFault;
> /**
> * <code>BusinessException</code>-
> *
> * Base class for business exceptions. It is only used by application
> developer.
> * Caller should have knowledge about how to handle this exception.
> *
> */
> @WebFault(name = "BusinessException", targetNamespace =
> AbstractException.TARGET_NAMESPACE)
> public class BusinessException extends AbstractException {
> /**
> * The exception message
> */
> private ExceptionMessage exceptionMessage;
> /**
> * Serial Version ID to compare if the class version has changed in
> * serialization/deserialization.
> */
> private static final long serialVersionUID = -4466271192745954077L;
> /**
> * Default logical exception code
> */
> private static final String INFO_CODE = "error.business";
> /**
> * @see com.mycompany.platform.exception.checked.AbstractException
> */
> public BusinessException(final Throwable nested) {
> super(nested);
> }
> /**
> * @see com.mycompany.platform.exception.checked.AbstractException
> */
> public BusinessException(final String msg, final Throwable nested,
> final String newInfoCode, final Serializable... args) {
> super(msg, nested, newInfoCode, args);
> }
> /**
> * @see com.mycompany.platform.exception.checked.AbstractException
> */
> public BusinessException(final String msg, final String newInfoCode,
> final Serializable... args) {
> super(msg, newInfoCode, args);
> }
> /**
> * @see com.mycompany.platform.exception.checked.AbstractException
> */
> public BusinessException(final String msg, final Throwable nested) {
> super(msg, nested);
> }
> /**
> * @see com.mycompany.platform.exception.checked.AbstractException
> */
> public BusinessException(final Throwable nested, final String
> newInfoCode) {
> super(nested, newInfoCode);
> }
> /**
> * @see com.mycompany.platform.exception.checked.AbstractException
> */
> public BusinessException(final String msg) {
> super(msg);
> }
> /**
> * @see com.mycompany.platform.exception.checked.AbstractException
> */
> public BusinessException() {
> super();
> }
> /**
> * <code>getDefaultInformationCode</code>-
> *
> * Returns the default exception key to use if none is specified when
> the
> * exception is thrown.
> *
> * @return <code>String</code> default information code
> */
> @Override
> public String getDefaultInformationCode() {
> return INFO_CODE;
> }
>
> public ExceptionMessage getExceptionMessage() {
> return exceptionMessage;
> }
> public void setExceptionMessage(final ExceptionMessage
> exceptionMessage) {
> this.exceptionMessage = exceptionMessage;
> }
> }
> package com.mycompany.platform.exception.checked;
> import javax.xml.bind.annotation.XmlRootElement;
> import javax.xml.bind.annotation.XmlType;
> /**
> *
> * <code>ExceptionMessage</code>-
> *
> * The ExceptionMessage object that is used in the application to create
> * and utilize error messages. This object provides methods to create an
> * ExceptionMessage object and setters/getters for its various attributes.
> *
> */
> @XmlRootElement(name = "ExceptionMessage")
> @XmlType(propOrder = {
> "classCause",
> "severity",
> "exceptionMessage",
> "displayMessage",
> "code",
> "informationCode",
> "uniqueID",
> "userResolution",
> "exceptionCause",
> "stack"
> })
> public class ExceptionMessage {
> /**
> * WARN <code>String</code> definition
> */
> public static final String WARN = "WARN";
> /**
> * DEBUG <code>String</code> definition
> */
> public static final String DEBUG = "DEBUG";
> /**
> * ERROR <code>String</code> definition
> */
> public static final String ERROR = "ERROR";
> /**
> * FATAL <code>String</code> definition
> */
> public static final String FATAL = "FATAL";
> /**
> * INFO <code>String</code> definition
> */
> public static final String INFO = "INFO";
> /**
> * PERIOD <code>String</code> definition. Generates a new line.
> */
> private static final String PERIOD = ".\n";
> private String displayMessage;
> private String severity;
> private String informationCode;
> private String userResolution;
> private String uniqueID;
> private String stack;
> private String exceptionCause;
> private String exceptionMsg;
> private String classCause;
> private int code;
> /**
> * Creates a new <code>ExceptionMessage</code> object.
> */
> public ExceptionMessage() {
> super();
> }
> /**
> * Creates a new <code>ExceptionMessage</code> object.
> *
> * @param informationCode <code>String<code> information code
> * @param theMessage <code>String</code> textual error message
> * @param theCode <code>String</code> error message code
> * @param theSeverity <code>String</code> error severity
> * @param theUserResolution <code>String</code> user resolution
> */
> public ExceptionMessage(final String informationCode,
> final String theMessage, final int theCode,
> final String theSeverity, final String theUserResolution) {
> this.displayMessage = theMessage.replace("\"", "");
> this.code = theCode;
> this.severity = theSeverity;
> this.informationCode = informationCode;
> this.userResolution = theUserResolution.replace("\"", "");
> }
> public void setInformationCode(String informationCode) {
> this.informationCode = informationCode;
> }
> public void setUserResolution(String userResolution) {
> this.userResolution = userResolution.replace("\"", "");
> }
> /**
> * <code>getClassCause</code>-
> * Returns the <code>String<code> Class name that caused the exception.
> *
> * @return <code>String<code> Class name that caused the exception
> */
> public String getClassCause() {
> return classCause;
> }
> /**
> * <code>setClassCause</code>-
> * Sets the <code>String<code> Class name that caused the exception.
> *
> * @param classCause <code>String<code> Class name that caused the
> exception
> */
> public void setClassCause(String classCause) {
> this.classCause = classCause;
> }
> /**
> * <code>setCode</code>-
> *
> * Sets the code.
> *
> * @param theCode <code>int</code> to set
> *
> */
> public void setCode(final int theCode) {
> this.code = theCode;
> }
> /**
> * <code>getCode</code>-
> *
> * Returns the code.
> *
> * @return <code>int<code> code
> */
> public int getCode() {
> return this.code;
> }
> /**
> * <code>setDisplayMessage</code>-
> *
> * Sets the message.
> *
> * @param aDisplayMessage <code>String</code> to set
> *
> */
> public void setDisplayMessage(final String aDisplayMessage) {
> this.displayMessage = aDisplayMessage.replace("\"", "");
> }
> /**
> * <code>getDisplayMessage</code>-
> *
> * Returns the message.
> *
> * @return <code>String</code> display message
> */
> public String getDisplayMessage() {
> return this.displayMessage;
> }
> /**
> * <code>setSeverity</code>-
> *
> * Sets the severity.
> *
> * @param theSeverity <code>String</code> to set
> *
> */
> public void setSeverity(final String theSeverity) {
> this.severity = theSeverity;
> }
> /**
> * <code>getSeverity</code>-
> *
> * Returns the severity.
> *
> * @return <code>String</code> severity
> */
> public String getSeverity() {
> return this.severity;
> }
> /**
> * <code>getInformationCode</code>-
> *
> * Returns the logicalName
> *
> * @return <code>String</code> information code
> *
> */
> public String getInformationCode() {
> return this.informationCode;
> }
> /**
> * <code>getUserResolution</code>-
> *
> * Returns the userResolution.
> *
> * @return <code>String</code> user resolution
> *
> */
> public String getUserResolution() {
> return this.userResolution;
> }
> /**
> * <code>getUniqueID</code>-
> *
> * Returns the unique id for the exception
> *
> * @return <code>String</code> Unique ID
> */
> public String getUniqueID() {
> return this.uniqueID;
> }
> /**
> * <code>setUniqueID</code>-
> *
> * Sets the unique id for the exception
> *
> * @param uniqueID <code>String</code> to set
> */
> public void setUniqueID(final String uniqueID) {
> this.uniqueID = uniqueID;
> }
> /**
> * <code>getStack</code>-
> *
> * Gets the stack trace of the exception that occurred
> *
> * @return <code>String</code> containing exception stack
> */
> public String getStack() {
> return stack;
> }
> /**
> * <code>setStack</code>-
> * Sets the stack trace of the exception that occurred
> *
> * @param stackTraceElements <code>String</code> representation of the
> stack to set
> *
> */
> public void setStack(
> final String stack) {
> this.stack = stack;
> }
> /**
> * <code>setStackTrace</code>-
> * Sets the stack trace of the exception that occurred
> *
> * @param stackTraceElements <code>StackTraceElement</code> array to set
> *
> */
> public void setStackTrace(
> final StackTraceElement[] stack) {
> if (stack != null)
> {
> StringBuilder builder = new StringBuilder();
> this.stack = ExceptionMessage.convert(builder,
> stack).toString();
> }
> }
> /**
> * <code>getExceptionCause</code>-
> *
> * This method returns the original exception cause. A cause is another
> * <code>Throwable</code> that caused the final exception to be thrown.
> * It is also known as the chained exception facility, as the cause can,
> * itself, have a cause, and so on,
> * leading to a "chain" of exceptions, each caused by another. Please note
> * that this cause may return null if no cause was set using the @see
> * {@link ExceptionMessage.setExceptionCause()} method.
> *
> * @return <code>String</code> representation of the
> <code>Throwable</code> chained that was set
> */
> public String getExceptionCause() {
> return this.exceptionCause;
> }
> /**
> * <code>setExceptionCause</code>-
> *
> * This method sets the original exception cause. A cause is another
> * <code>Throwable</code> that caused the final exception to be thrown.
> The cause
> * facility was added new in release 1.4. It is also known as the chained
> * exception facility, as the cause can, itself, have a cause, and so on,
> * leading to a "chain" of exceptions, each caused by another. this is
> * OPTIONAL value and only to be used if there is a strong need to display
> * the cause of the exception.
> *
> * @param exceptionCause <code>String</code> representation of
> <code>Throwable</code> chained exception to set
> */
> public void setExceptionCause(final String exceptionCause) {
> this.exceptionCause = exceptionCause;
> }
> /**
> * <code>setExceptionCausing</code>-
> *
> * This method sets the original exception cause. A cause is another
> * <code>Throwable</code> that caused the final exception to be thrown.
> The cause
> * facility was added new in release 1.4. It is also known as the chained
> * exception facility, as the cause can, itself, have a cause, and so on,
> * leading to a "chain" of exceptions, each caused by another. this is
> * OPTIONAL value and only to be used if there is a strong need to display
> * the cause of the exception.
> *
> * @param exceptionCause <code>Throwable</code> exception to set
> */
> public void setExceptionCausing(final Throwable exceptionCausing) {
> this.exceptionCause = exceptionCausing.toString();
> }
> /**
> * <code>getExceptionMessage</code>-
> *
> * Returns the detail message string of this throwable. The detail message
> * string of this <code>Throwable</code> instance (which may be null).
> *
> * @return <code>String</code> exceptionMessage
> */
> public String getExceptionMessage() {
> return this.exceptionMsg;
> }
> /**
> * <code>setExceptionMessage</code>-
> *
> * Sets the detail message string of the <code>Throwable<code> that the
> exception
> * message may use to display. this is optional and may not always be set.
> *
> * @param exceptionMessage <code>String</code> exception message to set.
> *
> */
> public void setExceptionMessage(final String exceptionMessage) {
> this.exceptionMsg = exceptionMessage;
> }
> /* (non-Javadoc)
> * @see java.lang.Object#toString()
> */
> @Override
> public String toString() {
> final StringBuilder stringBuilder = new StringBuilder();
> stringBuilder.append("Unique ID: ");
> stringBuilder.append(this.uniqueID);
> stringBuilder.append(PERIOD);
> stringBuilder.append("Information Code: ");
> stringBuilder.append(this.informationCode);
> stringBuilder.append(PERIOD);
> stringBuilder.append("Error Code: ");
> stringBuilder.append(this.code);
> stringBuilder.append(PERIOD);
> stringBuilder.append("User Message: ");
> stringBuilder.append(this.displayMessage);
> stringBuilder.append(PERIOD);
> stringBuilder.append("Message: ");
> stringBuilder.append(this.exceptionMsg);
> stringBuilder.append(PERIOD);
> stringBuilder.append("Resolution: ");
> stringBuilder.append(this.userResolution);
> stringBuilder.append(PERIOD);
> stringBuilder.append("Exception Class: ");
> stringBuilder.append(this.classCause);
> stringBuilder.append(PERIOD);
> stringBuilder.append("Detailed Stack Trace: ");
> stringBuilder.append(this.stack);
> stringBuilder.append(PERIOD);
> stringBuilder.append("Cause: ");
> stringBuilder.append(this.exceptionCause);
> return stringBuilder.toString();
> }
> /**
> * <code>convert</code>-
> *
> * Converts the stack trace of an exception into
> <code>StringBuilder</code> from <code>StackTraceElement</code>.
> *
> * @param newStringBuilder <code>StringBuilder</code> buffer to which
> will be appended
> * @param stack <code>StackTraceElement</code> array of elements to
> append to the stack
> *
> * @return <code>StringBuilder</code> of the exception stack trace
> */
> public static StringBuilder convert(final StringBuilder newStringBuilder,
> final StackTraceElement[] stack) {
> StringBuilder result = newStringBuilder;
> if (stack != null && stack.length > 0) {
> if (result == null) {
> result = new StringBuilder();
> }
> result.append(stack[0]);
> for (int i = 1; i < stack.length; i++) {
> result.append('\n');
> result.append(stack[i]);
> }
> } else {
> if (result == null) {
> result = new StringBuilder();
> }
> }
> return result;
> }
> }
> {code}
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators:
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira