I want to return objects that have JPA annotations on them from a service, but dont want the JPA annotations in the client object (stored in a shared module). Is there a way to use an abstrac class or interface?
Thanks, James On Wed, Feb 24, 2010 at 1:33 PM, PrSd <[email protected]> wrote: > > Hello, > > I am injecting a SAML Assertion in a SOAP Header from the SOAPClient and > then issuing a service request to a CXF webservice. On the service end I > have a JAX WS SOAP Handler that intercepts and unmarshals the header. The > client and service handlers are from Glen Mazza's weblog. > http://www.jroller.com/gmazza/entry/using_the_opensaml_library_in > > I am still including them incase any customary changes I may have made > messed up something. So here it is > > ------------------------------------------------------------------------------------------------------ > SOAPClient: > ------------------------------------------------------------------------------------------------------ > package com.hsc.security.saml.soap; > > import java.io.IOException; > import java.net.MalformedURLException; > import java.net.URL; > > import java.util.ArrayList; > import java.util.List; > import java.util.Map; > import java.util.Properties; > import java.util.Set; > import javax.xml.namespace.QName; > import javax.xml.soap.SOAPElement; > import javax.xml.soap.SOAPEnvelope; > import javax.xml.soap.SOAPHeader; > import javax.xml.soap.SOAPMessage; > import javax.xml.ws.BindingProvider; > import javax.xml.ws.Service; > import javax.xml.ws.handler.MessageContext; > import javax.xml.ws.handler.soap.SOAPHandler; > import javax.xml.ws.handler.soap.SOAPMessageContext; > import javax.xml.ws.soap.SOAPBinding; > > import com.syscom.hsc.web.IBpmService; > > public class SpringWSClient { > > String wsdlString = > "http://localhost:9088/bpm-servicesCXF/services/IBpmService"; > //String wsdlString = > "http://localhost:9088/bpm-servicesCXF/services/IBpmService?wsdl=IBpmService.wsdl"; > private static final QName SERVICE_NAME > = new QName("http://web.hsc.syscom.com", "BPMWebService"); > > private static final QName PORT_NAME > = new QName("http://web.hsc.syscom.com", "BpmServicePort"); > > > > > public static String xmlFileNamePath = "BpmServices.xml"; > > public static void main(String [] args){ > > SpringWSClient ws = new SpringWSClient(); > System.out.println("Starting SOAP request"); > Service service = Service.create(SERVICE_NAME); > > //BPMWebService bpmServices = new BPMWebService(SERVICE_NAME); > HeaderHandlerResolver handlerResolver = new > HeaderHandlerResolver(); > service.setHandlerResolver(handlerResolver); > > > // Endpoint Address > String endpointAddress = > "http://localhost:9088/bpm-servicesCXF/services/IBpmService"; > try { > java.net.URL url = new URL(endpointAddress); > } catch (MalformedURLException e1) { > // TODO Auto-generated catch block > e1.printStackTrace(); > } > > // Add a port to the Service > > IBpmService client = service.getPort(IBpmService.class); > > Map<String, Object> requestContext = > ((BindingProvider)client).getRequestContext(); > requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, > endpointAddress); > requestContext.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, > Boolean.TRUE); > > String username = "kpham"; > String password = "hdfuhgdg"; > String category = "GETFULLEOPINWRK"; > int max = -1; > Properties arguments = null; > String response =null; > try { > response = > client.findTaskListUsingLoginCreds(username, password, > category, arguments, max); > //response = client.findTaskList(category, arguments, > max); > > System.out.println("Response: " + response); > } catch (Exception e) { > // TODO Auto-generated catch block > e.printStackTrace(); > } > > > } > > ------------------------------------------------------------------------------------------------------ > ClientSAMLHandler > ------------------------------------------------------------------------------------------------------ > public class ClientSAMLHandler implements SOAPHandler<SOAPMessageContext> { > > // change this to redirect output if desired > private static PrintStream out = System.out; > > public static final String WS_SECURITY_NS_URI = > > "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; > > private static final Set<QName> HEADERS = new HashSet<QName>(); > /* static { > HEADERS.add(new QName(WSConstants.WSSE_NS, "Security")); > HEADERS.add(new QName(WSConstants.WSSE11_NS, "Security")); > HEADERS.add(new QName(WSConstants.ENC_NS, "EncryptedData")); > > } > */ > public Set getHeaders() { > //return HEADERS; > return null; > } > > public boolean handleMessage(SOAPMessageContext smc) { > Boolean outboundProperty = (Boolean) > smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); > > if (outboundProperty.booleanValue()) { > out.println("(debug) Adding SAML token to outbound message from > client"); > System.out.println("(debug) Adding SAML token to outbound message > from client"); > > try { > DefaultBootstrap.bootstrap(); > SOAPMessage message = smc.getMessage(); > SOAPPart soapPart = message.getSOAPPart(); > SOAPEnvelope soapEnvelope = soapPart.getEnvelope(); > Name wsseHeaderName = soapEnvelope.createName("Security", > "wsse", WS_SECURITY_NS_URI); > if (soapEnvelope.getHeader() == null) { > soapEnvelope.addHeader(); > } > SOAPHeaderElement securityElement = soapEnvelope.getHeader() > .addHeaderElement(wsseHeaderName); > > AssertionBuilder ab = new AssertionBuilder(); > Assertion assertion = ab.buildObject(); > assertion.setVersion(SAMLVersion.VERSION_20); > assertion.setID("123"); // in reality, must be unique for all > assertions > assertion.setIssueInstant(new DateTime()); > > IssuerBuilder ib = new IssuerBuilder(); > Issuer myIssuer = ib.buildObject(); > myIssuer.setValue("http://localhost:9088"); > assertion.setIssuer(myIssuer); > > SubjectBuilder sb = new SubjectBuilder(); > Subject mySubject = sb.buildObject(); > NameIDBuilder nb = new NameIDBuilder(); > NameID myNameID = nb.buildObject(); > myNameID.setValue("p8admin"); > myNameID.setFormat(NameIdentifier.X509_SUBJECT); > mySubject.setNameID(myNameID); > assertion.setSubject(mySubject); > > // user authenticated via X509 token > AuthnStatementBuilder asb = new AuthnStatementBuilder(); > AuthnStatement myAuthnStatement = asb.buildObject(); > myAuthnStatement.setAuthnInstant(new DateTime()); > AuthnContextBuilder acb = new AuthnContextBuilder(); > AuthnContext myACI = acb.buildObject(); > AuthnContextClassRefBuilder accrb = new > AuthnContextClassRefBuilder(); > AuthnContextClassRef accr = accrb.buildObject(); > accr.setAuthnContextClassRef(AuthnContext.X509_AUTHN_CTX); > myACI.setAuthnContextClassRef(accr); > myAuthnStatement.setAuthnContext(myACI); > assertion.getAuthnStatements().add(myAuthnStatement); > > // user can double even numbers > AuthzDecisionStatementBuilder adsb = new > AuthzDecisionStatementBuilder(); > AuthzDecisionStatement ads = adsb.buildObject(); > ads.setDecision(DecisionTypeEnumeration.PERMIT); > ads.setResource("DoubleIt"); > ActionBuilder actb = new ActionBuilder(); > Action act = actb.buildObject(); > // arbitrary unique tag to define "namespace" of action > // note SAML actions not defined in an XSD -- XAMCL normally > used instead > act.setNamespace("urn:doubleit:doubleitactions"); > act.setAction("DoubleEvenNumbers"); > ads.getActions().add(act); > assertion.getAuthzDecisionStatements().add(ads); > > // user has math degree > AttributeStatementBuilder attstmtb = new > AttributeStatementBuilder(); > AttributeStatement attstmt = attstmtb.buildObject(); > AttributeBuilder attbldr = new AttributeBuilder(); > Attribute attr = attbldr.buildObject(); > attr.setName("degree"); > attr.setNameFormat("http://www.example.org/DoubleIt/Security"); > XSStringBuilder stringBuilder = (XSStringBuilder) Configuration > .getBuilderFactory().getBuilder(XSString.TYPE_NAME); > XSString stringValue = stringBuilder > .buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, > XSString.TYPE_NAME); > stringValue.setValue("Mathematics"); > attr.getAttributeValues().add(stringValue); > attstmt.getAttributes().add(attr); > assertion.getAttributeStatements().add(attstmt); > > // marshall Assertion Java class into XML > MarshallerFactory marshallerFactory = Configuration > .getMarshallerFactory(); > Marshaller marshaller = marshallerFactory > .getMarshaller(assertion); > Element assertionElement = marshaller.marshall(assertion); > securityElement.appendChild(soapPart.importNode( > assertionElement, true)); > > //Print out the outbound SOAP message to System.out > message.writeTo(System.out); > System.out.println(""); > > } catch (Exception e) { > e.printStackTrace(); > } > } > else{ > try { > > //This handler does nothing with the response from the Web > Service so > //we just print out the SOAP message. > SOAPMessage message = smc.getMessage(); > message.writeTo(System.out); > System.out.println(""); > > } catch (Exception ex) { > ex.printStackTrace(); > } > } > return true; > } > > public boolean handleFault(SOAPMessageContext smc) { > out.println("Exception in Client handler: "); > SOAPMessage message = smc.getMessage(); > try { > message.writeTo(out); > out.println(""); // just to add a newline > } catch (Exception e) { > out.println("Unable to write exception for exception: " > + e.toString()); > } > return true; > } > > // nothing to clean up > public void close(MessageContext messageContext) { > } > > } > > > } > > The SOAP Client then issues the service request, the Service JAX WS Handler > intercepts the incoming message. The handleMessage is invoked, however I see > a SOAPFaultException being thrown - > ------------------------------------------------------------------------------------------------------ > [2/24/10 14:10:33:974 EST] 00000022 HandlerChainI 1 invoking handlers, > direction: inbound > [2/24/10 14:10:33:974 EST] 00000022 HandlerChainI 1 invoking handler of > type com.syscom.hsc.web.soap.ServiceSAMLHandler > [2/24/10 14:10:33:974 EST] 00000022 SystemOut O Inside handleMessage > ----> > [2/24/10 14:10:33:974 EST] 00000022 SystemOut O Inside handleMessage > ----> outboundProperty.booleanValue() false > [2/24/10 14:10:33:974 EST] 00000022 SystemOut O Inside handleMessage > ----> sh.toString()[soap:Header: null] > [2/24/10 14:10:33:974 EST] 00000022 SystemOut O Inside handleMessage > ----> wsseElement.getLocalName()Security > [2/24/10 14:10:33:974 EST] 00000022 SystemOut O Inside handleMessage > ----> > wsseElement.getNamespaceURI()http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd > [2/24/10 14:10:33:974 EST] 00000022 SystemOut O Inside handleMessage > ----> assertionElement.getLocalName()Assertion > [2/24/10 14:10:33:974 EST] 00000022 SystemOut O Inside handleMessage > ----> > assertionElement.getNamespaceURI()urn:oasis:names:tc:SAML:2.0:assertion > [2/24/10 14:10:34:224 EST] 00000022 Configuration W > org.opensaml.xml.Configuration validateJCEProviders The JCE providers > currently configured in the JVM do not support > required capabilities for XML Encryption, either the 'AES' cipher algorithm > or the 'ISO10126Padding' padding scheme > > handleMessage raised exception > javax.xml.ws.soap.SOAPFaultException: > Internal Error: local part cannot be "null" when creating a QName > at > com.syscom.hsc.web.soap.ServiceSAMLHandler.createSOAPFaultException(ServiceSAMLHandler.java:253) > at > com.syscom.hsc.web.soap.ServiceSAMLHandler.handleMessage(ServiceSAMLHandler.java:234) > at > com.syscom.hsc.web.soap.ServiceSAMLHandler.handleMessage(ServiceSAMLHandler.java:1) > at > org.apache.cxf.jaxws.handler.HandlerChainInvoker.invokeHandleMessage(HandlerChainInvoker.java:335) > at > org.apache.cxf.jaxws.handler.HandlerChainInvoker.invokeHandlerChain(HandlerChainInvoker.java:253) > at > org.apache.cxf.jaxws.handler.HandlerChainInvoker.invokeProtocolHandlers(HandlerChainInvoker.java:131) > .----------------------------------------------------------------------------------------------------- > > > > > Here is the ServiceHandler > ------------------------------------------------------------------------------------------------------ > SAMLServiceHandler > ------------------------------------------------------------------------------------------------------ > package com.syscom.hsc.web.soap; > import java.io.PrintStream; > import java.util.HashSet; > import java.util.Iterator; > import java.util.List; > import java.util.Set; > > import javax.annotation.PostConstruct; > import javax.annotation.PreDestroy; > import javax.xml.namespace.QName; > import javax.xml.soap.SOAPBody; > import javax.xml.soap.SOAPConstants; > import javax.xml.soap.SOAPException; > import javax.xml.soap.SOAPFactory; > import javax.xml.soap.SOAPFault; > import javax.xml.soap.SOAPHeader; > import javax.xml.soap.SOAPMessage; > import javax.xml.ws.handler.MessageContext; > import javax.xml.ws.handler.soap.SOAPHandler; > import javax.xml.ws.handler.soap.SOAPMessageContext; > import javax.xml.ws.soap.SOAPFaultException; > > import org.apache.ws.security.WSConstants; > import org.opensaml.Configuration; > import org.opensaml.DefaultBootstrap; > import org.opensaml.saml2.core.Action; > import org.opensaml.saml2.core.Assertion; > import org.opensaml.saml2.core.Attribute; > import org.opensaml.saml2.core.AttributeStatement; > import org.opensaml.saml2.core.AuthnContext; > import org.opensaml.saml2.core.AuthnStatement; > import org.opensaml.saml2.core.AuthzDecisionStatement; > import org.opensaml.xml.XMLObject; > import org.opensaml.xml.io.Unmarshaller; > import org.opensaml.xml.io.UnmarshallerFactory; > import org.w3c.dom.Element; > import org.w3c.dom.Node; > > import org.opensaml.common.xml.SAMLConstants; > > import com.syscom.hsc.web.security.saml.SAMLCredential; > > /* > * This sample SOAP Protocol Handler for DoubleIt checks for X.509 > authentication, > * attribute of Math degree, and authorization to double even numbers. > */ > public class ServiceSAMLHandler implements SOAPHandler<SOAPMessageContext> { > > // change this to redirect output if desired > private static PrintStream out = System.out; > > private static String WS_SECURITY_URI = > > "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; > private static final String HANDLER_NAME = "ServiceSAMLHandler"; > > > private static final Set<QName> HEADERS = new HashSet<QName>(); > /* static { > HEADERS.add(new QName(WSConstants.WSSE_NS, "Security")); > HEADERS.add(new QName(WSConstants.WSSE11_NS, "Security")); > HEADERS.add(new QName(WSConstants.ENC_NS, "EncryptedData")); > } > */ > @PostConstruct > public void init() { > out.println("------------------------------------"); > out.println("In Handler " + HANDLER_NAME + ":init()"); > out.println("Exiting Handler " + HANDLER_NAME + ":init()"); > out.println("------------------------------------"); > } > > @PreDestroy > public void destroy() { > out.println("------------------------------------"); > out.println("In Handler " + HANDLER_NAME + ":destroy()"); > out.println("Exiting Handler " + HANDLER_NAME + ":destroy()"); > out.println("------------------------------------"); > } > > > public Set <QName> getHeaders() { > //return HEADERS; > return null; > } > > public boolean handleMessage(SOAPMessageContext smc) { > out.println("Inside handleMessage ----> "); > Boolean outboundProperty = (Boolean) smc > .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); > > > if (!outboundProperty.booleanValue()) { > out.println("Inside handleMessage ----> > outboundProperty.booleanValue() "+outboundProperty.booleanValue()); > logToSystemOut(smc); > Element assertionElement; > > try { > // check for SOAP Header > SOAPHeader sh = smc.getMessage().getSOAPHeader(); > out.println("Inside handleMessage ----> > sh.toString()"+sh.toString()); > if (sh == null) { > throw createSOAPFaultException("Missing SOAP Header", true); > } > > // check for wsse:security element under SOAP Header > Node wsseElement = sh.getFirstChild(); > out.println("Inside handleMessage ----> > wsseElement.getLocalName()"+wsseElement.getLocalName()); > out.println("Inside handleMessage ----> > wsseElement.getNamespaceURI()"+wsseElement.getNamespaceURI()); > > if (wsseElement == null || > !"Security".equals(wsseElement.getLocalName()) > || !WS_SECURITY_URI.equals(wsseElement.getNamespaceURI())) > { > throw createSOAPFaultException("Missing or invalid > WS-Security Header", > true); > } > > // check for SAML assertion under wsse:security element > assertionElement = (Element) wsseElement.getFirstChild(); > > out.println("Inside handleMessage ----> > assertionElement.getLocalName()"+assertionElement.getLocalName()); > out.println("Inside handleMessage ----> > assertionElement.getNamespaceURI()"+assertionElement.getNamespaceURI()); > if (assertionElement == null > || !"Assertion".equals(assertionElement.getLocalName()) > || > !SAMLConstants.SAML20_NS.equals(assertionElement.getNamespaceURI())) { > throw createSOAPFaultException("Missing or invalid SAML > Assertion", true); > } > > // Unmarshall SAML Assertion into an OpenSAML Java object. > DefaultBootstrap.bootstrap(); > UnmarshallerFactory unmarshallerFactory = Configuration > .getUnmarshallerFactory(); > Unmarshaller unmarshaller = unmarshallerFactory > .getUnmarshaller(assertionElement); > Assertion samlAssertion = (Assertion) unmarshaller > .unmarshall(assertionElement); > > /* > * Below code works with OpenSAML API to check Authentication, > * Authorization, and attributes. Using the XPath API with the > * assertionElement above would probably be an easier and more > * readable option. > */ > //Check for Subject > out.println("Subject from Service > Handler"+samlAssertion.getSubject().getNameID().getValue()); > //SAMLCredential samlCred = new > SAMLCredential(samlAssertion.getSubject().getNameID(), samlAssertion); > > SAMLCredential.setNameID(samlAssertion.getSubject().getNameID()); > SAMLCredential.setAuthenticationAssertion(samlAssertion); > > > // Check for X509 authentication, error otherwise > List authStmtList = samlAssertion.getAuthnStatements(); > if (authStmtList == null || authStmtList.size() < 1 > || authStmtList.size() > 1) { > throw createSOAPFaultException("Missing Authentication > Statement.", true); > } else { > AuthnStatement authStmt = (AuthnStatement) > authStmtList.get(0); > if > (!AuthnContext.X509_AUTHN_CTX.equals(authStmt.getAuthnContext() > .getAuthnContextClassRef().getAuthnContextClassRef())) > { > throw createSOAPFaultException("Only X.509 authentication > supported.", > true); > } > } > > // Check if math degree, error otherwise > List asList = samlAssertion.getAttributeStatements(); > /* if (asList == null || asList.size() == 0) { > throw createSOAPFaultException("Degree/Major is missing.", > true); > } else { > boolean hasMathDegree = false; > for (Iterator it = asList.iterator(); it.hasNext();) { > AttributeStatement as = it.next(); > List attList = as.getAttributes(); > if (attList == null || attList.size() == 0) { > throw createSOAPFaultException("Degree/major is > missing.", true); > } else { > for (Iterator it2 = attList.iterator(); it2.hasNext();) > { > Attribute att = it2.next(); > if (!att.getName().equals("degree")) { > continue; > } else { > List xoList = att.getAttributeValues(); > if (xoList == null || xoList.size() < 1 || > xoList.size() > 1) { > throw createSOAPFaultException("Degree/major > is missing.", > true); > } else { > XMLObject xmlObj = xoList.get(0); > if > (xmlObj.getDOM().getFirstChild().getTextContent() > .equals("Mathematics")) { > hasMathDegree = true; > } > } > } > } > } > } > if (hasMathDegree == false) { > throw createSOAPFaultException( > "Must have Mathematics degree to run DoubleIt.", > true); > } > } > * > // If even number being doubled, make sure user has permission > SOAPBody sb = smc.getMessage().getSOAPBody(); > > if (sb.getFirstChild() == null || > sb.getFirstChild().getFirstChild() == null) { > throw createSOAPFaultException("Invalid SOAP Body", true); > } else { > Integer intValue = new > Integer(sb.getFirstChild().getFirstChild() > .getTextContent()); > if ((intValue.intValue() % 2) == 0) { // if even > List adsList = samlAssertion > .getAuthzDecisionStatements(); > if (adsList == null || adsList.size() < 1 || > adsList.size() > 1) { > throw createSOAPFaultException( > "Missing or invalid Authorization Decision > Statement", true); > } else { > Boolean canDoubleEven = false; > AuthzDecisionStatement ads = (AuthzDecisionStatement) > adsList.get(0); > List actList = ads.getActions(); > for (Iterator it = actList.iterator(); it.hasNext();) { > Action action = (Action) it.next(); > if ("DoubleEvenNumbers".equals(action.getAction())) > { > canDoubleEven = true; > break; > } > } > if (canDoubleEven == false) { > throw createSOAPFaultException( > "Missing authorization to double even > numbers.", true); > } > } > } > }*/ > } catch (Exception e) { > throw createSOAPFaultException("Internal Error: " + > e.getMessage(), false); > } > } > return true; > } > > /* > * Convenience function used to generate a generic SOAPFaultException > */ > private SOAPFaultException createSOAPFaultException(String faultString, > Boolean clientFault) { > try { > System.out.println("*********clientFault***********"+clientFault); > String faultCode = clientFault ? "Client" : "Server"; > System.out.println("*********faultCode***********"+faultCode); > SOAPFault fault = SOAPFactory.newInstance().createFault(); > System.out.println("*********faultString***********"+faultString); > fault.setFaultString(faultString); > fault.setFaultCode(new QName(SOAPConstants.URI_NS_SOAP_ENVELOPE, > faultCode)); > return new SOAPFaultException(fault); > } catch (SOAPException e) { > throw new RuntimeException("Error creating SOAP Fault message, > faultString: " > + faultString); > } > } > > public boolean handleFault(SOAPMessageContext smc) { > > out.println("------------------------------------"); > out.println("In Handler " + HANDLER_NAME + ":handleFault()"); > logToSystemOut(smc); > out.println("Exiting Handler " + HANDLER_NAME + > ":handleFault()"); > out.println("------------------------------------"); > > return true; > } > > // nothing to clean up > public void close(MessageContext messageContext) { > out.println("------------------------------------"); > out.println("In Handler " + HANDLER_NAME + ":close()"); > out.println("Exiting Handler " + HANDLER_NAME + ":close()"); > out.println("------------------------------------"); > > } > > /* > * Check the MESSAGE_OUTBOUND_PROPERTY in the context to see if this is > an > * outgoing or incoming message. Write a brief message to the print > stream > * and output the message. The writeTo() method can throw SOAPException > or > * IOException > */ > private void logToSystemOut(SOAPMessageContext smc) { > Boolean outboundProperty = (Boolean) smc > .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); > > if (outboundProperty.booleanValue()) { > out.println("\nIncoming message to web service provider:"); > } else { > out.println("\nOutgoing message from web service provider:"); > } > > SOAPMessage message = smc.getMessage(); > try { > message.writeTo(out); > out.println(""); // just to add a newline > } catch (Exception e) { > out.println("Exception in handler: " + e); > } > } > > } > > I am not sure what the local part here is and how can I circumvent it from > being Null. Any clue or suggestions will be well appreciated. > > > > > -- > View this message in context: > http://old.nabble.com/local-part-cannot-be-%22null%22-when-creating-a-QName-tp27714287p27714287.html > Sent from the cxf-user mailing list archive at Nabble.com. > >
