|
Axis 2 example source code file (EndpointInterfaceDescriptionImpl.java)
The Axis 2 EndpointInterfaceDescriptionImpl.java source code
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.axis2.jaxws.description.impl;
import org.apache.axis2.AxisFault;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisOperationFactory;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.description.EndpointDescription;
import org.apache.axis2.jaxws.description.EndpointInterfaceDescription;
import org.apache.axis2.jaxws.description.EndpointInterfaceDescriptionJava;
import org.apache.axis2.jaxws.description.EndpointInterfaceDescriptionWSDL;
import org.apache.axis2.jaxws.description.OperationDescription;
import org.apache.axis2.jaxws.description.ServiceDescriptionWSDL;
import org.apache.axis2.jaxws.description.builder.DescriptionBuilderComposite;
import org.apache.axis2.jaxws.description.builder.MDQConstants;
import org.apache.axis2.jaxws.description.builder.MethodDescriptionComposite;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.wsdl.Definition;
import javax.wsdl.PortType;
import javax.xml.namespace.QName;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
//import org.apache.log4j.BasicConfigurator;
/** @see ../EndpointInterfaceDescription */
class EndpointInterfaceDescriptionImpl
implements EndpointInterfaceDescription, EndpointInterfaceDescriptionJava,
EndpointInterfaceDescriptionWSDL {
private EndpointDescriptionImpl parentEndpointDescription;
private ArrayList<OperationDescription> operationDescriptions =
new ArrayList<OperationDescription>();
// This may be an actual Service Endpoint Interface -OR- it may be a service implementation class that did not
// specify an @WebService.endpointInterface.
private Class seiClass;
private DescriptionBuilderComposite dbc;
//Logging setup
private static final Log log = LogFactory.getLog(EndpointInterfaceDescriptionImpl.class);
// ===========================================
// ANNOTATION related information
// ===========================================
// ANNOTATION: @WebService
private WebService webServiceAnnotation;
private String webServiceTargetNamespace;
private String webService_Name;
// ANNOTATION: @SOAPBinding
// Note this is the Type-level annotation. See OperationDescription for the Method-level annotation
private SOAPBinding soapBindingAnnotation;
// TODO: Should this be using the jaxws annotation values or should that be wrappered?
private javax.jws.soap.SOAPBinding.Style soapBindingStyle;
// Default value per JSR-181 MR Sec 4.7 "Annotation: javax.jws.soap.SOAPBinding" pg 28
public static final javax.jws.soap.SOAPBinding.Style SOAPBinding_Style_DEFAULT =
javax.jws.soap.SOAPBinding.Style.DOCUMENT;
private javax.jws.soap.SOAPBinding.Use soapBindingUse;
// Default value per JSR-181 MR Sec 4.7 "Annotation: javax.jws.soap.SOAPBinding" pg 28
public static final javax.jws.soap.SOAPBinding.Use SOAPBinding_Use_DEFAULT =
javax.jws.soap.SOAPBinding.Use.LITERAL;
private javax.jws.soap.SOAPBinding.ParameterStyle soapParameterStyle;
// Default value per JSR-181 MR Sec 4.7 "Annotation: javax.jws.soap.SOAPBinding" pg 28
public static final javax.jws.soap.SOAPBinding.ParameterStyle SOAPBinding_ParameterStyle_DEFAULT =
javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED;
void addOperation(OperationDescription operation) {
operationDescriptions.add(operation);
}
EndpointInterfaceDescriptionImpl(Class sei, EndpointDescriptionImpl parent) {
seiClass = sei;
parentEndpointDescription = parent;
// Per JSR-181 all methods on the SEI are mapped to operations regardless
// of whether they include an @WebMethod annotation. That annotation may
// be present to customize the mapping, but is not required (p14)
// TODO: Testcases that do and do not include @WebMethod anno
for (Method method : getSEIMethods(seiClass)) {
OperationDescription operation = new OperationDescriptionImpl(method, this);
addOperation(operation);
}
}
/**
* Build from AxisService
*
* @param parent
*/
EndpointInterfaceDescriptionImpl(EndpointDescriptionImpl parent) {
parentEndpointDescription = parent;
AxisService axisService = parentEndpointDescription.getAxisService();
if (axisService != null) {
ArrayList publishedOperations = axisService.getPublishedOperations();
Iterator operationsIterator = publishedOperations.iterator();
while (operationsIterator.hasNext()) {
AxisOperation axisOperation = (AxisOperation)operationsIterator.next();
addOperation(new OperationDescriptionImpl(axisOperation, this));
}
}
}
/**
* Construct as Provider-based endpoint which does not have specific WSDL operations. Since there
* are no specific WSDL operations in this case, there will be a single generic operation that
* will accept any incoming operation.
*
* @param dbc
* @param parent
*/
EndpointInterfaceDescriptionImpl(DescriptionBuilderComposite dbc,
EndpointDescriptionImpl parent) {
if (log.isDebugEnabled()) {
log.debug("Creating a EndpointInterfaceDescription for a generic WSDL-less provider");
}
parentEndpointDescription = parent;
this.dbc = dbc;
// Construct the generic provider AxisOperation to use then construct
// an OperactionDescription for it.
AxisOperation genericProviderAxisOp = null;
try {
genericProviderAxisOp =
AxisOperationFactory.getOperationDescription(WSDLConstants.WSDL20_2006Constants.MEP_URI_IN_OUT);
} catch (AxisFault e) {
if (log.isDebugEnabled()) {
log.debug("Unable to build AxisOperation for generic Provider; caught exception.", e);
}
// TODO: NLS & RAS
throw ExceptionFactory.makeWebServiceException("Caught exception trying to create AxisOperation",
e);
}
genericProviderAxisOp.setName(new QName(JAXWS_NOWSDL_PROVIDER_OPERATION_NAME));
OperationDescription opDesc = new OperationDescriptionImpl(genericProviderAxisOp, this);
addOperation(opDesc);
AxisService axisService = getEndpointDescription().getAxisService();
axisService.addOperation(genericProviderAxisOp);
}
/**
* Build an EndpointInterfaceDescription from a DescriptionBuilderComposite. This EID has
* WSDL operations associated with it. It could represent an SEI-based endpoint built from
* WSDL or annotations, OR it could represent a Provider-based enpoint built from WSDL. It will
* not represent a Provider-based endpoint built without WSDL (which does not know about
* specific WSDL operations). For that type of EID, see:
* @see #EndpointInterfaceDescriptionImpl(DescriptionBuilderComposite dbc, EndpointDescriptionImpl parent)
* @param dbc
* @param isClass
* @param parent
*/
EndpointInterfaceDescriptionImpl(DescriptionBuilderComposite dbc,
boolean isClass,
EndpointDescriptionImpl parent) {
parentEndpointDescription = parent;
this.dbc = dbc;
//TODO: yikes! ...too much redirection, consider setting this in higher level
getEndpointDescription().getAxisService()
.setTargetNamespace(getEndpointDescriptionImpl().getTargetNamespace());
//TODO: Determine if the isClass parameter is really necessary
// Per JSR-181 all methods on the SEI are mapped to operations regardless
// of whether they include an @WebMethod annotation. That annotation may
// be present to customize the mapping, but is not required (p14)
// TODO: Testcases that do and do not include @WebMethod anno
//We are processing the SEI composite
//For every MethodDescriptionComposite in this list, call OperationDescription
//constructor for it, then add this operation
//Retrieve the relevent method composites for this dbc (and those in the superclass chain)
Iterator<MethodDescriptionComposite> iter = retrieveReleventMethods(dbc);
if (log.isDebugEnabled())
log.debug("EndpointInterfaceDescriptionImpl: Finished retrieving methods");
MethodDescriptionComposite mdc = null;
while (iter.hasNext()) {
mdc = iter.next();
//TODO: Verify that this classname is truly always the wrapper class
mdc.setDeclaringClass(dbc.getClassName());
// Only add if it is a method that would be or is in the WSDL i.e.
// don't create an OperationDescriptor for the MDC representing the
// constructor
if (DescriptionUtils.createOperationDescription(mdc.getMethodName())) {
//First check if this operation already exists on the AxisService, if so
//then use that in the description hierarchy
AxisService axisService = getEndpointDescription().getAxisService();
AxisOperation axisOperation = axisService
.getOperation(OperationDescriptionImpl.determineOperationQName(mdc));
OperationDescription operation =
new OperationDescriptionImpl(mdc, this, axisOperation);
if (axisOperation == null) {
// This axisOperation did not already exist on the AxisService, and so was created
// with the OperationDescription, so we need to add the operation to the service
((OperationDescriptionImpl)operation).addToAxisService(axisService);
}
if (log.isDebugEnabled())
log.debug("EID: Just added operation= " + operation.getOperationName());
addOperation(operation);
}
}
if (log.isDebugEnabled())
log.debug("EndpointInterfaceDescriptionImpl: Finished Adding operations");
//TODO: Need to process the other annotations that can exist, on the server side
// and at the class level.
// They are, as follows:
// HandlerChain (181)
// SoapBinding (181)
// WebServiceRefAnnot (List) (JAXWS)
// BindingTypeAnnot (JAXWS Sec. 7.8 -- Used to set either the AS.endpoint, or AS.SoapNSUri)
// WebServiceContextAnnot (JAXWS via injection)
}
private static Method[] getSEIMethods(Class sei) {
// Per JSR-181 all methods on the SEI are mapped to operations regardless
// of whether they include an @WebMethod annotation. That annotation may
// be present to customize the mapping, but is not required (p14)
Method[] seiMethods = sei.getMethods();
ArrayList methodList = new ArrayList();
if (sei != null) {
for (Method method : seiMethods) {
if (method.getDeclaringClass().getName().equals("java.lang.Object")) {
continue;
}
methodList.add(method);
if (!Modifier.isPublic(method.getModifiers())) {
// JSR-181 says methods must be public (p14)
// TODO NLS
ExceptionFactory.makeWebServiceException("SEI methods must be public");
}
// TODO: other validation per JSR-181
}
}
return (Method[])methodList.toArray(new Method[methodList.size()]);
// return seiMethods;
}
/**
* Update a previously created EndpointInterfaceDescription with information from an annotated
* SEI. This should only be necessary when the this was created with WSDL. In this case, the
* information from the WSDL is augmented based on the annotated SEI.
*
* @param sei
*/
void updateWithSEI(Class sei) {
if (seiClass != null && seiClass != sei)
// TODO: It probably is invalid to try reset the SEI; but this isn't the right error processing
throw new UnsupportedOperationException(
"The seiClass is already set; reseting it is not supported");
else if (seiClass != null && seiClass == sei)
// We've already done the necessary updates for this SEI
return;
else if (sei != null) {
seiClass = sei;
// Update (or possibly add) the OperationDescription for each of the methods on the SEI.
for (Method seiMethod : getSEIMethods(seiClass)) {
if (getOperation(seiMethod) != null) {
// If an OpDesc already exists with this java method set on it, then the OpDesc has already
// been updated for this method, so skip it.
continue;
}
// At this point (for now at least) the operations were created with WSDL previously.
// If they had been created from an annotated class and no WSDL, then the seiClass would have
// already been set so we would have taken other branches in this if test. (Note this could
// change once AxisServices can be built from annotations by the ServiceDescription class).
// Since the operations were created from WSDL, they will not have a java method, which
// comes from the SEI, set on them yet.
//
// Another consideration is that currently Axis2 does not support overloaded WSDL operations.
// That means there will only be one OperationDesc build from WSDL. Still another consideration is
// that the JAXWS async methods which may exist on the SEI will NOT exist in the WSDL. An example
// of these methods for the WSDL operation:
// String echo(String)
// optionally generated JAX-WS SEI methods from the tooling; take note of the annotation specifying the
// operation name
// @WebMethod(operationName="echo" ...)
// Response<String> echoStringAsync(String)
// @WebMethod(operationName="echo" ...)
// Future<?> echoStringAsync(String, AsyncHandler)
//
// So given all the above, the code does the following based on the operation QName
// (which might also be the java method name; see determineOperationQName for details)
// (1) If an operationDesc does not exist, add it.
// (2) If an operationDesc does exist but does not have a java method set on it, set it
// (3) If an operationDesc does exist and has a java method set on it already, add a new one.
//
// TODO: May need to change when Axis2 supports overloaded WSDL operations
// TODO: May need to change when ServiceDescription can build an AxisService from annotations
// Get the QName for this java method and then update (or add) the appropriate OperationDescription
// See comments below for imporant notes about the current implementation.
// NOTE ON OVERLOADED OPERATIONS
// Axis2 does NOT currently support overloading WSDL operations.
QName seiOperationQName =
OperationDescriptionImpl.determineOperationQName(seiMethod);
OperationDescription[] updateOpDesc = getOperation(seiOperationQName);
if (updateOpDesc == null || updateOpDesc.length == 0) {
// This operation wasn't defined in the WSDL. Note that the JAX-WS async methods
// which are defined on the SEI are not defined as operations in the WSDL.
// Although they usually specific the same OperationName as the WSDL operation,
// there may be cases where they do not.
// TODO: Is this path an error path, or can the async methods specify different operation names than the
// WSDL operation?
OperationDescription operation = new OperationDescriptionImpl(seiMethod, this);
addOperation(operation);
} else {
// Currently Axis2 does not support overloaded operations. That means that even if the WSDL
// defined overloaded operations, there would still only be a single AxisOperation, and it
// would be the last operation encounterd.
// HOWEVER the generated JAX-WS async methods (see above) may (will always?) have the same
// operation name and so will come down this path; they need to be added.
// TODO: When Axis2 starts supporting overloaded operations, then this logic will need to be changed
// TODO: Should we verify that these are the async methods before adding them, and treat it as an error otherwise?
// Loop through all the opdescs; if one doesn't currently have a java method set, set it
// If all have java methods set, then add a new one. Assume we'll need to add a new one.
boolean addOpDesc = true;
for (OperationDescription checkOpDesc : updateOpDesc) {
if (checkOpDesc.getSEIMethod() == null) {
// TODO: Should this be checking (somehow) that the signature matches? Probably not an issue until overloaded WSDL ops are supported.
//Make sure that this is not one of the 'async' methods associated with
//this operation. If it is, let it be created as its own opDesc.
if (!DescriptionUtils.isAsync(seiMethod)) {
((OperationDescriptionImpl) checkOpDesc).setSEIMethod(seiMethod);
addOpDesc = false;
break;
}
}
}
if (addOpDesc) {
OperationDescription operation =
new OperationDescriptionImpl(seiMethod, this);
addOperation(operation);
}
}
}
}
}
/**
* Return the OperationDescriptions corresponding to a particular Java method name. Note that an
* array is returned because a method could be overloaded.
*
* @param javaMethodName String representing a Java Method Name
* @return
*/
// FIXME: This is confusing; some getOperations use the QName from the WSDL or annotation; this one uses the java method name; rename this signature I think; add on that takes a String but does a QName lookup against the WSDL/Annotation
public OperationDescription[] getOperationForJavaMethod(String javaMethodName) {
if (DescriptionUtils.isEmpty(javaMethodName)) {
return null;
}
ArrayList<OperationDescription> matchingOperations = new ArrayList
Other Axis 2 examples (source code examples)Here is a short list of links related to this Axis 2 EndpointInterfaceDescriptionImpl.java source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.