@Test public void testForWebFaultAnnotationInExceptions() throws Exception { StringBuffer errors = new StringBuffer(); List<Class<?>> classes = PackageClassReader.getClasses( CurrencyException.class, Throwable.class, ClassFilter.CLASSES_ONLY); for (Class<?> clazz : getApplicationExceptions(classes)) { WebFault annotation = clazz.getAnnotation(WebFault.class); if (annotation == null) { errors.append("Class ").append(clazz.getName()) .append(" misses WebFault annotation\n"); continue; } String name = annotation.name(); if (!name.equals(clazz.getSimpleName())) { errors.append("Class ").append(clazz.getName()) .append(" uses a WebFault name annotation that ") .append("does not match the class name.\n"); } } if (errors.length() > 0) { fail("Exceptions without constructor(String):\n" + errors.toString()); } }
/** * Creates a SOAP fault from the exception and populates the message as well * as the detail. The detail object is read from the method getFaultInfo of * the throwable if present * * @param exception the cause exception * @return SOAP fault from given Throwable */ @SuppressWarnings("unchecked") private JAXBElement<Fault> createFaultFromException(final Throwable exception) { WebFault webFault = exception.getClass().getAnnotation(WebFault.class); if (webFault == null || webFault.targetNamespace() == null) { throw new RuntimeException("The exception " + exception.getClass().getName() + " needs to have an WebFault annotation with name and targetNamespace", exception); } QName name = new QName(webFault.targetNamespace(), webFault.name()); Object faultObject; try { Method method = exception.getClass().getMethod("getFaultInfo"); faultObject = method.invoke(exception); } catch (Exception e) { throw new RuntimeCamelException("Exception while trying to get fault details", e); } Fault fault = new Fault(); fault.setFaultcode(FAULT_CODE_SERVER); fault.setFaultstring(exception.getMessage()); Detail detailEl = new ObjectFactory().createDetail(); @SuppressWarnings("rawtypes") JAXBElement<?> faultDetailContent = new JAXBElement(name, faultObject.getClass(), faultObject); detailEl.getAny().add(faultDetailContent); fault.setDetail(detailEl); return new ObjectFactory().createFault(fault); }
public String getFaultBean() { if (faultBean != null && faultBean.length() > 0) { // Return the faultBean if it was already calculated return faultBean; } else { // Load up the WebFault annotation and get the faultBean. // @WebFault may not be present WebFault annotation = getAnnoWebFault(); if (annotation != null && annotation.faultBean() != null && annotation.faultBean().length() > 0) { faultBean = annotation.faultBean(); } else { // There is no default. But it seems reasonable to return // the fault info type. faultBean = getFaultInfo(); // The faultBean still may be "" at this point. The JAXWS runtime // is responsible for finding/buildin a representative fault bean. } } return faultBean; }
public String getName() { if (name.length() > 0) { return name; } else { // Load the annotation. The annotation may not be present in WSGen cases WebFault annotation = this.getAnnoWebFault(); if (annotation != null && annotation.name().length() > 0) { name = annotation.name(); } else { // The default is undefined. // The JAX-WS layer may use the fault bean information to determine the name } } return name; }
public String getTargetNamespace() { if (targetNamespace.length() > 0) { return targetNamespace; } else { // Load the annotation. The annotation may not be present in WSGen cases WebFault annotation = this.getAnnoWebFault(); if (annotation != null && annotation.targetNamespace().length() > 0) { targetNamespace = annotation.targetNamespace(); } else { // The default is undefined // The JAX-WS layer may use the fault bean information to determine the name } } return targetNamespace; }
/** * Creates a SOAP fault from the exception and populates the message as well * as the detail. The detail object is read from the method getFaultInfo of * the throwable if present * * @param exception the cause exception * @return SOAP fault from given Throwable */ @SuppressWarnings("unchecked") private JAXBElement<Fault> createFaultFromException(final Throwable exception) { WebFault webFault = exception.getClass().getAnnotation(WebFault.class); if (webFault == null || webFault.targetNamespace() == null) { throw new RuntimeException("The exception " + exception.getClass().getName() + " needs to have an WebFault annotation with name and targetNamespace", exception); } QName name = new QName(webFault.targetNamespace(), webFault.name()); Object faultObject; try { Method method = exception.getClass().getMethod("getFaultInfo"); faultObject = method.invoke(exception); } catch (Exception e) { throw new RuntimeCamelException("Exception while trying to get fault details", e); } Fault fault = new Fault(); Faultcode code = new Faultcode(); code.setValue(FAULT_CODE_SERVER); fault.setCode(code); Reasontext text = new Reasontext(); text.setValue(exception.getMessage()); text.setLang("en"); fault.setReason(new Faultreason().withText(text)); Detail detailEl = new ObjectFactory().createDetail(); @SuppressWarnings("rawtypes") JAXBElement<?> faultDetailContent = new JAXBElement(name, faultObject.getClass(), faultObject); detailEl.getAny().add(faultDetailContent); fault.setDetail(detailEl); return new ObjectFactory().createFault(fault); }
@SuppressWarnings("unchecked") private void addExceptions(Method method) { Class<?>[] exTypes = method.getExceptionTypes(); for (Class<?> exType : exTypes) { WebFault webFault = exType.getAnnotation(WebFault.class); if (webFault != null) { QName faultName = new QName(webFault.targetNamespace(), webFault.name()); faultNameToException.put(faultName, (Class<? extends Exception>) exType); } } }
public WebFault getAnnoWebFault() { if (annotation == null) { if (isDBC()) { annotation = this.composite.getWebFaultAnnot(); } } return annotation; }
public String getMessageName(){ if(messageName.length()>0){ return name; }else{ WebFault annotation= this.getAnnoWebFault(); if(annotation!=null && annotation.messageName().length()>0){ messageName=annotation.messageName(); }else{ // The default is undefined. // The JAX-WS layer may use the fault bean information to determine the name } } return messageName; }
/** * This method will be used to attach @WebFault annotation data to the * <code>DescriptionBuilderComposite</code> * * @param composite - <code>DescriptionBuilderComposite</code> */ private void attachWebFaultAnnotation(DescriptionBuilderComposite composite) { WebFault webFault = (WebFault)ConverterUtils.getAnnotation( WebFault.class, serviceClass); if (webFault != null) { WebFaultAnnot webFaultAnnot = WebFaultAnnot.createWebFaultAnnotImpl(); webFaultAnnot.setFaultBean(webFault.faultBean()); webFaultAnnot.setName(webFault.name()); webFaultAnnot.setTargetNamespace(webFault.targetNamespace()); webFaultAnnot.setMessageName(webFault.messageName()); composite.setWebFaultAnnot(webFaultAnnot); } }
private void write(Fault fault) throws JClassAlreadyExistsException { String className = Names.customExceptionClassName(fault); JDefinedClass cls = cm._class(className, ClassType.CLASS); JDocComment comment = cls.javadoc(); if(fault.getJavaDoc() != null){ comment.add(fault.getJavaDoc()); comment.add("\n\n"); } for (String doc : getJAXWSClassComment()) { comment.add(doc); } cls._extends(java.lang.Exception.class); //@WebFault JAnnotationUse faultAnn = cls.annotate(WebFault.class); faultAnn.param("name", fault.getBlock().getName().getLocalPart()); faultAnn.param("targetNamespace", fault.getBlock().getName().getNamespaceURI()); JType faultBean = fault.getBlock().getType().getJavaType().getType().getType(); //faultInfo filed JFieldVar fi = cls.field(JMod.PRIVATE, faultBean, "faultInfo"); //add jaxb annotations fault.getBlock().getType().getJavaType().getType().annotate(fi); fi.javadoc().add("Java type that goes as soapenv:Fault detail element."); JFieldRef fr = JExpr.ref(JExpr._this(), fi); //Constructor JMethod constrc1 = cls.constructor(JMod.PUBLIC); JVar var1 = constrc1.param(String.class, "message"); JVar var2 = constrc1.param(faultBean, "faultInfo"); constrc1.javadoc().addParam(var1); constrc1.javadoc().addParam(var2); JBlock cb1 = constrc1.body(); cb1.invoke("super").arg(var1); cb1.assign(fr, var2); //constructor with Throwable JMethod constrc2 = cls.constructor(JMod.PUBLIC); var1 = constrc2.param(String.class, "message"); var2 = constrc2.param(faultBean, "faultInfo"); JVar var3 = constrc2.param(Throwable.class, "cause"); constrc2.javadoc().addParam(var1); constrc2.javadoc().addParam(var2); constrc2.javadoc().addParam(var3); JBlock cb2 = constrc2.body(); cb2.invoke("super").arg(var1).arg(var3); cb2.assign(fr, var2); //getFaultInfo() method JMethod fim = cls.method(JMod.PUBLIC, faultBean, "getFaultInfo"); fim.javadoc().addReturn().add("returns fault bean: "+faultBean.fullName()); JBlock fib = fim.body(); fib._return(fi); fault.setExceptionClass(cls); }
private boolean generateExceptionBean(TypeElement thrownDecl, String beanPackage) { if (!builder.isServiceException(thrownDecl.asType())) return false; String exceptionName = ClassNameInfo.getName(thrownDecl.getQualifiedName().toString()); if (processedExceptions.contains(exceptionName)) return false; processedExceptions.add(exceptionName); WebFault webFault = thrownDecl.getAnnotation(WebFault.class); String className = beanPackage+ exceptionName + BEAN.getValue(); Collection<MemberInfo> members = ap_generator.collectExceptionBeanMembers(thrownDecl); boolean isWSDLException = isWSDLException(members, thrownDecl); String namespace = typeNamespace; String name = exceptionName; FaultInfo faultInfo; if (isWSDLException) { TypeMirror beanType = getFaultInfoMember(members).getParamType(); faultInfo = new FaultInfo(TypeMonikerFactory.getTypeMoniker(beanType), true); namespace = webFault.targetNamespace().length()>0 ? webFault.targetNamespace() : namespace; name = webFault.name().length()>0 ? webFault.name() : name; faultInfo.setElementName(new QName(namespace, name)); seiContext.addExceptionBeanEntry(thrownDecl.getQualifiedName(), faultInfo, builder); return false; } if (webFault != null) { namespace = webFault.targetNamespace().length()>0 ? webFault.targetNamespace() : namespace; name = webFault.name().length()>0 ? webFault.name() : name; className = webFault.faultBean().length()>0 ? webFault.faultBean() : className; } JDefinedClass cls = getCMClass(className, CLASS); faultInfo = new FaultInfo(className, false); if (duplicateName(className)) { builder.processError(WebserviceapMessages.WEBSERVICEAP_METHOD_EXCEPTION_BEAN_NAME_NOT_UNIQUE( typeElement.getQualifiedName(), thrownDecl.getQualifiedName())); } boolean canOverWriteBean = builder.canOverWriteClass(className); if (!canOverWriteBean) { builder.log("Class " + className + " exists. Not overwriting."); seiContext.addExceptionBeanEntry(thrownDecl.getQualifiedName(), faultInfo, builder); return false; } if (seiContext.getExceptionBeanName(thrownDecl.getQualifiedName()) != null) return false; //write class comment - JAXWS warning JDocComment comment = cls.javadoc(); for (String doc : GeneratorBase.getJAXWSClassComment(ToolVersion.VERSION.MAJOR_VERSION)) { comment.add(doc); } // XmlElement Declarations writeXmlElementDeclaration(cls, name, namespace); // XmlType Declaration //members = sortMembers(members); XmlType xmlType = thrownDecl.getAnnotation(XmlType.class); String xmlTypeName = (xmlType != null && !xmlType.name().equals("##default")) ? xmlType.name() : exceptionName; String xmlTypeNamespace = (xmlType != null && !xmlType.namespace().equals("##default")) ? xmlType.namespace() : typeNamespace; writeXmlTypeDeclaration(cls, xmlTypeName, xmlTypeNamespace, members); writeMembers(cls, members); seiContext.addExceptionBeanEntry(thrownDecl.getQualifiedName(), faultInfo, builder); return true; }
protected boolean isWSDLException(Collection<MemberInfo> members, TypeElement thrownDecl) { WebFault webFault = thrownDecl.getAnnotation(WebFault.class); return webFault != null && members.size() == 2 && getFaultInfoMember(members) != null; }
private boolean generateExceptionBean(TypeElement thrownDecl, String beanPackage) { if (!builder.isServiceException(thrownDecl.asType())) return false; String exceptionName = ClassNameInfo.getName(thrownDecl.getQualifiedName().toString()); if (processedExceptions.contains(exceptionName)) return false; processedExceptions.add(exceptionName); WebFault webFault = thrownDecl.getAnnotation(WebFault.class); String className = beanPackage+ exceptionName + BEAN.getValue(); Collection<MemberInfo> members = ap_generator.collectExceptionBeanMembers(thrownDecl); boolean isWSDLException = isWSDLException(members, thrownDecl); String namespace = typeNamespace; String name = exceptionName; FaultInfo faultInfo; if (isWSDLException) { TypeMirror beanType = getFaultInfoMember(members).getParamType(); faultInfo = new FaultInfo(TypeMonikerFactory.getTypeMoniker(beanType), true); namespace = webFault.targetNamespace().length()>0 ? webFault.targetNamespace() : namespace; name = webFault.name().length()>0 ? webFault.name() : name; faultInfo.setElementName(new QName(namespace, name)); seiContext.addExceptionBeanEntry(thrownDecl.getQualifiedName(), faultInfo, builder); return false; } if (webFault != null) { namespace = webFault.targetNamespace().length()>0 ? webFault.targetNamespace() : namespace; name = webFault.name().length()>0 ? webFault.name() : name; className = webFault.faultBean().length()>0 ? webFault.faultBean() : className; } JDefinedClass cls = getCMClass(className, CLASS); faultInfo = new FaultInfo(className, false); if (duplicateName(className)) { builder.processError(WebserviceapMessages.WEBSERVICEAP_METHOD_EXCEPTION_BEAN_NAME_NOT_UNIQUE( typeElement.getQualifiedName(), thrownDecl.getQualifiedName())); } boolean canOverWriteBean = builder.canOverWriteClass(className); if (!canOverWriteBean) { builder.log("Class " + className + " exists. Not overwriting."); seiContext.addExceptionBeanEntry(thrownDecl.getQualifiedName(), faultInfo, builder); return false; } if (seiContext.getExceptionBeanName(thrownDecl.getQualifiedName()) != null) { return false; } addGeneratedFile(className); //write class comment - JAXWS warning JDocComment comment = cls.javadoc(); for (String doc : GeneratorBase.getJAXWSClassComment(ToolVersion.VERSION.MAJOR_VERSION)) { comment.add(doc); } // XmlElement Declarations writeXmlElementDeclaration(cls, name, namespace); // XmlType Declaration //members = sortMembers(members); XmlType xmlType = thrownDecl.getAnnotation(XmlType.class); String xmlTypeName = (xmlType != null && !xmlType.name().equals("##default")) ? xmlType.name() : exceptionName; String xmlTypeNamespace = (xmlType != null && !xmlType.namespace().equals("##default")) ? xmlType.namespace() : typeNamespace; writeXmlTypeDeclaration(cls, xmlTypeName, xmlTypeNamespace, members); writeMembers(cls, members); seiContext.addExceptionBeanEntry(thrownDecl.getQualifiedName(), faultInfo, builder); return true; }
private void checkFailure(org.apache.camel.Exchange camelExchange, Exchange cxfExchange) throws Fault { final Throwable t; if (camelExchange.isFailed()) { org.apache.camel.Message camelMsg = camelExchange.hasOut() ? camelExchange.getOut() : camelExchange.getIn(); if (camelMsg.isFault()) { t = camelMsg.getBody(Throwable.class); } else { t = camelExchange.getException(); } cxfExchange.getInMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT); if (t instanceof Fault) { cxfExchange.getInMessage().put(FaultMode.class, FaultMode.CHECKED_APPLICATION_FAULT); throw (Fault)t; } else if (t != null) { // This is not a CXF Fault. Build the CXF Fault manually. Fault fault = new Fault(t); if (fault.getMessage() == null) { // The Fault has no Message. This is the case if it has // no message, for example was a NullPointerException. fault.setMessage(t.getClass().getSimpleName()); } WebFault faultAnnotation = t.getClass().getAnnotation(WebFault.class); Object faultInfo = null; try { Method method = t.getClass().getMethod("getFaultInfo"); faultInfo = method.invoke(t, new Object[0]); } catch (Exception e) { // do nothing here } if (faultAnnotation != null && faultInfo == null) { // t has a JAX-WS WebFault annotation, which describes // in detail the Web Service Fault that should be thrown. Add the // detail. Element detail = fault.getOrCreateDetail(); Element faultDetails = detail.getOwnerDocument() .createElementNS(faultAnnotation.targetNamespace(), faultAnnotation.name()); detail.appendChild(faultDetails); } throw fault; } } }
/** * @param cls * @return true if this is a JAX-WS or JAX-WS generated class */ public static final boolean isJAXWSClass(Class cls) { // TODO Processing all of these annotations is very expensive. We need to cache the // result in a static WeakHashMap<Class, Boolean> // Kinds of generated classes: Service, Provider, Impl, Exception, Holder // Or the class is in the jaxws.xml.ws package // Check for Impl WebService wsAnn = (WebService)getAnnotation(cls,WebService.class); if (wsAnn != null) { return true; } // Check for service WebServiceClient wscAnn = (WebServiceClient)getAnnotation(cls,WebServiceClient.class); if (wscAnn != null) { return true; } // Check for provider WebServiceProvider wspAnn = (WebServiceProvider) getAnnotation(cls,WebServiceProvider.class); if (wspAnn != null) { return true; } // Check for Exception WebFault wfAnn = (WebFault)getAnnotation(cls,WebFault.class); if (wfAnn != null) { return true; } // Check for Holder if (Holder.class.isAssignableFrom(cls)) { return true; } // Check for a javax.xml.ws.Service class instance if (Service.class.isAssignableFrom(cls)) { return true; } String className = cls.getPackage() == null ? null : cls.getPackage().getName(); if (className != null && className.startsWith("javax.xml.ws") && !className.startsWith("javax.xml.ws.wsaddressing")) { return true; } return false; }
private boolean generateExceptionBean(ClassDeclaration thrownDecl, String beanPackage) { if (!builder.isServiceException(thrownDecl)) return false; String exceptionName = ClassNameInfo.getName(thrownDecl.getQualifiedName()); if (processedExceptions.contains(exceptionName)) return false; processedExceptions.add(exceptionName); WebFault webFault = thrownDecl.getAnnotation(WebFault.class); String className = beanPackage+ exceptionName + BEAN; Collection<MemberInfo> members = APT_GENERATOR.collectExceptionBeanMembers(thrownDecl); boolean isWSDLException = isWSDLException(members, thrownDecl); String namespace = typeNamespace; String name = exceptionName; FaultInfo faultInfo; if (isWSDLException) { TypeMirror beanType = getFaultInfoMember(members).getParamType(); faultInfo = new FaultInfo(TypeMonikerFactory.getTypeMoniker(beanType), true); namespace = webFault.targetNamespace().length()>0 ? webFault.targetNamespace() : namespace; name = webFault.name().length()>0 ? webFault.name() : name; faultInfo.setElementName(new QName(namespace, name)); seiContext.addExceptionBeanEntry(thrownDecl.getQualifiedName(), faultInfo, builder); return false; } if (webFault != null) { namespace = webFault.targetNamespace().length()>0 ? webFault.targetNamespace() : namespace; name = webFault.name().length()>0 ? webFault.name() : name; className = webFault.faultBean().length()>0 ? webFault.faultBean() : className; } JDefinedClass cls = getCMClass(className, CLASS); faultInfo = new FaultInfo(className, false); if (duplicateName(className)) { builder.onError(WebserviceapMessages.WEBSERVICEAP_METHOD_EXCEPTION_BEAN_NAME_NOT_UNIQUE(typeDecl.getQualifiedName(), thrownDecl.getQualifiedName())); } boolean canOverWriteBean = builder.canOverWriteClass(className); if (!canOverWriteBean) { builder.log("Class " + className + " exists. Not overwriting."); seiContext.addExceptionBeanEntry(thrownDecl.getQualifiedName(), faultInfo, builder); return false; } if (seiContext.getExceptionBeanName(thrownDecl.getQualifiedName()) != null) return false; //write class comment - JAXWS warning JDocComment comment = cls.javadoc(); for (String doc : GeneratorBase.getJAXWSClassComment(builder.getSourceVersion())) { comment.add(doc); } // XmlElement Declarations writeXmlElementDeclaration(cls, name, namespace); // XmlType Declaration //members = sortMembers(members); XmlType xmlType = thrownDecl.getAnnotation(XmlType.class); String xmlTypeName = (xmlType != null && !xmlType.name().equals("##default")) ? xmlType.name() : exceptionName; String xmlTypeNamespace = (xmlType != null && !xmlType.namespace().equals("##default")) ? xmlType.namespace() : typeNamespace; writeXmlTypeDeclaration(cls, xmlTypeName, xmlTypeNamespace, members); writeMembers(cls, members); seiContext.addExceptionBeanEntry(thrownDecl.getQualifiedName(), faultInfo, builder); return true; }
protected boolean isWSDLException(Collection<MemberInfo> members, ClassDeclaration thrownDecl) { WebFault webFault = thrownDecl.getAnnotation(WebFault.class); if (webFault == null) return false; return !(members.size() != 2 || getFaultInfoMember(members) == null); }
/** * The FaultDescriptionImpl class will only be used to describe exceptions declared to be thrown * by a service that has a WebFault annotation. No generic exception should ever have a * FaultDescription associated with it. It is the responsibility of the user of the * FaultDescriptionImpl class to avoid instantiating this object for non-annotated generic * exceptions. * * @param exceptionClass an exception declared to be thrown by the service on which this * FaultDescription may apply. * @param beanName fully qualified package+classname of the bean associated with this * exception * @param annotation the WebFault annotation object on this exception class * @param parent the OperationDescription that is the parent of this FaultDescription */ FaultDescriptionImpl(Class exceptionClass, WebFault annotation, OperationDescription parent) { this.exceptionClass = exceptionClass; this.annotation = annotation; this.parent = parent; }
/** * Gets the SOAP fault name from the class with {@link WebFault @WebFault}. * * @param clazz the class that represents fault * @return fault name */ protected static String getExFaultName(Class clazz) { WebFault annotation = AnnotationUtils.findAnnotation(clazz, WebFault.class); return annotation.name(); }
public WebFault getAnnoWebFault();