CXF Marshalling error - cxf

i am getting "Marshalling Error: class tavant.twms.integration.layer.component.hsmComponent.HSMAddressResponse nor any of its super class is known to this context". i have added the annotations as well, but still not resolved. below are my files,
cxf-servlet.xml
<bean id="integrationServiceImpl" class="tavant.twms.integration.layer.IntegrationServiceImpl"/>
<jaxws:endpoint id="integrationService" implementor="#integrationServiceImpl" address="/IntegrationService">
<jaxws:dataBinding>
<bean class="org.apache.cxf.jaxb.JAXBDataBinding"/>
</jaxws:dataBinding>
</jaxws:endpoint>
#webmethod
public Object fetchHSMAddressDetails(String addressxml){
securityHelper.populateIntegrationUser();
HSMAddressRequestDocumentDTO requestDTO = null;
HSMAddressRequest request = null;
try {
requestDTO = HSMAddressRequestDocumentDTO.Factory.parse((String) addressxml);
} catch (XmlException e) {
throw new RuntimeException(e);
}
if(requestDTO == null)
return null;
request = requestDTO.getHSMAddressRequest();
return hsmAddressFetch.fetchMelissaData(request);/* return type is HSMAddressResponse*/
}

Related

CXF: add element with namespace from message to SOAP header

How can I get the name (including namespace prefix) of root element in message (1st element in SOAP body) and add this information to SOAP header.
Is it possible to do so with outbound interceptor and in which phase is the namespace prefix available? Or is there other way how to do so?
EDIT:
I am able to get the element with its namespace prefix via message.getContent(OutputStream.class) but I don't want to modify row XML. Is there way how can I get namespace (e.g. from JAXB object in message) and set its namespace prefix? Then I can use the element name and my prefix in header.
I created interceptor where I get message (as JAXB object) and then I use reflection to get its root element (because it is not root element) from ObjectFactory. Then I get its namespace and name and I use it for SOAP header and I set namespace prefix for the namespace. My handleMessage method in interceptor is like the following:
public void handleMessage(SoapMessage message) throws Fault {
String rootElementNamespace = null;
String rootElementName = null;
Set<Class<?>> formats = message.getContentFormats();
List<?> messageContent = message.getContent(List.class);
Object responseMessage = null;
for (Object o : messageContent){
if (o != null && o.getClass().getAnnotation(XmlType.class) != null){
responseMessage = o;
break;
}
}
if(responseMessage == null){
return;
}
Class<? extends Object> messageContentClass = messageContent.get(0).getClass();
String packageOfMessageContentClass = messageContent.get(0).getClass().getPackage().getName();
try {
Class<?> objectFactory = Class.forName(packageOfMessageContentClass + ".ObjectFactory");
Method[] objectFactoryMethods = objectFactory.getMethods();
Method createMessageMethod = null;
for (Method m : objectFactoryMethods){
if (m.getParameterTypes().length == 1 && m.getParameterTypes()[0].equals(messageContentClass)){
createMessageMethod = m;
break;
}
}
if(createMessageMethod == null){
return;
}
XmlElementDecl xmlTypeAnnotation = createMessageMethod.getAnnotation(XmlElementDecl.class);
rootElementNamespace = xmlTypeAnnotation.namespace();
rootElementName = xmlTypeAnnotation.name();
} catch (ClassNotFoundException e) {
//...
}
Map<String, String> hmap = new HashMap<String, String>();
hmap.put(this.ROOT_PREFIX, rootElementNamespace);
message.put("soap.env.ns.map", hmap);
message.put("disable.outputstream.optimization", true);
try {
Header header = getMyHeader(this.ROOT_PREFIX + ":" + rootElementName); //method creates header with required info
message.getHeaders().add(header);
} catch (JAXBException | DatatypeConfigurationException e) {
//...
}
}
Better solution is welcome...

Custom HTTPBinding for HTTP Component

I'm trying to throw an exception if HTTP response code is anything other than 200 or 201. I tried to override http4.DefaultHttpBinding, but the class is never getting called. What am I doing wrong here?
public class CustomHttpBinding extends org.apache.camel.component.http4.DefaultHttpBinding {
Logger log = Logger.getLogger(CustomHttpBinding.class);
private static final Integer HTTP_OK = 200;
private static final Integer HTTP_CREATED = 201;
#Override
public void doWriteResponse(Message message, HttpServletResponse response, Exchange exchange) throws IOException {
Integer httpResponseCode = message.getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class);
if(!httpResponseCode.equals(HTTP_OK) && !httpResponseCode.equals(HTTP_CREATED) ) {
throw new IOException("HTTP error code for HLR response is " + httpResponseCode);
}
else {
super.doWriteResponse(message, response, exchange);
}
}
}
In xml:
<bean id="customHttpBinding" class="com.test.response.CustomHttpBinding" />
<endpoint uri="http4:${http.url.1}?httpBinding=#customHttpBinding&httpClient.socketTimeout=${http.notificationTimeout}" id="http4.1.to"/>
If the http response code is 300+, the binding will throw exception before it calls doWriteResponse(...). Try overriding writeResponse(...) in your custom binding, and verify that your binding is used.

StAX and namespaces

I am trying to convert some code from using DOM (via jDOM) to use StAX instead. At the same time I am migrating from DTD-based validation to XSD_based validation. Oh, and just for good measure I am introducing JAXB into the equation :)
Anyway, as an interim migration step I would like to allow users to still provide legacy documents (aka, using DTD and therefore no namespace). I will still validate the document using XSD, so the DTD is ignored. This works except that StAX (nor JAXB) seems to not like the non-namespaced document. I tried disabling namespace support (using javax.xml.stream.isNamespaceAware), but that did not have any effect. Explicitly adding xmlns to the document root fixed the problem, so I am fairly confident it is a namespacing issue.
Is there a way using StAX XMLEventReader to "introduce" a default namespace? Something along the lines of this approach (which is SAX specific), but for StAX...
Or any other ideas on how to achieve that?
An example document looks like:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.abstractembeddedcomponents.cid">
...
</hibernate-mapping>
The code I am currently using to read these documents is:
public JaxbRoot unmarshal(InputStream stream, Origin origin) {
try {
XMLEventReader staxReader = staxFactory().createXMLEventReader( stream );
try {
return unmarshal( staxReader, origin );
}
finally {
try {
staxReader.close();
}
catch ( Exception ignore ) {
}
}
}
catch ( XMLStreamException e ) {
throw new MappingException( "Unable to create stax reader", e, origin );
}
}
private XMLInputFactory staxFactory;
private XMLInputFactory staxFactory() {
if ( staxFactory == null ) {
staxFactory = buildStaxFactory();
}
return staxFactory;
}
#SuppressWarnings( { "UnnecessaryLocalVariable" })
private XMLInputFactory buildStaxFactory() {
XMLInputFactory staxFactory = XMLInputFactory.newInstance();
// tried with and without, no effect
//staxFactory.setProperty( "javax.xml.stream.isNamespaceAware", false );
return staxFactory;
}
#SuppressWarnings( { "unchecked" })
private JaxbRoot unmarshal(XMLEventReader staxEventReader, final Origin origin) {
XMLEvent event;
try {
event = staxEventReader.peek();
while ( event != null && !event.isStartElement() ) {
staxEventReader.nextEvent();
event = staxEventReader.peek();
}
}
catch ( Exception e ) {
throw new MappingException( "Error accessing stax stream", e, origin );
}
if ( event == null ) {
throw new MappingException( "Could not locate root element", origin );
}
final Schema validationSchema;
final Class jaxbTarget;
final String elementName = event.asStartElement().getName().getLocalPart();
if ( "entity-mappings".equals( elementName ) ) {
final Attribute attribute = event.asStartElement().getAttributeByName( ORM_VERSION_ATTRIBUTE_QNAME );
final String explicitVersion = attribute == null ? null : attribute.getValue();
validationSchema = validateXml ? resolveSupportedOrmXsd( explicitVersion ) : null;
jaxbTarget = JaxbEntityMappings.class;
}
else {
validationSchema = validateXml ? hbmSchema() : null;
jaxbTarget = JaxbHibernateMapping.class;
}
final Object target;
final ContextProvidingValidationEventHandler handler = new ContextProvidingValidationEventHandler();
try {
JAXBContext jaxbContext = JAXBContext.newInstance( jaxbTarget );
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setSchema( validationSchema );
unmarshaller.setEventHandler( handler );
target = unmarshaller.unmarshal( staxEventReader );
}
catch ( JAXBException e ) {
throw new MappingException( ... );
}
return new JaxbRoot( target, origin );
}
In my testing the DTD being there or not has no effect. And like I said before, simply changing
<hibernate-mapping package="org.hibernate.test.abstractembeddedcomponents.cid">
to
<hibernate-mapping xmlns="http://www.hibernate.org/xsd/hibernate-mapping" package="org.hibernate.test.abstractembeddedcomponents.cid">
fixes the failures I see, which are:
[org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'hibernate-mapping'.]
at ...
Caused by: org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'hibernate-mapping'.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:1916)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:705)
at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.startElement(ValidatorHandlerImpl.java:550)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.startElement(ValidatingUnmarshaller.java:78)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.InterningXmlVisitor.startElement(InterningXmlVisitor.java:60)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXEventConnector.handleStartElement(StAXEventConnector.java:247)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXEventConnector.bridge(StAXEventConnector.java:116)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:394)
... 27 more
This can be done by implementing a filter which adds a default namespace declaration to the first (i.e. root) StartELement event. StAX already provides the EventReaderDelegate utility class, where the peek() and nextEvent() methods need to be overridden.
Here's the code:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import javax.xml.stream.util.EventReaderDelegate;
/**
* Filter adding default namespace declaration to root element.
*/
public class NamespaceAddingEventReader extends EventReaderDelegate {
private final XMLEventFactory factory = XMLEventFactory.newInstance();
private final String namespaceURI;
private int startElementCount = 0;
public NamespaceAddingEventReader(XMLEventReader reader, String namespaceURI) {
super(reader);
this.namespaceURI = namespaceURI;
}
/**
* Duplicate event with additional namespace declaration.
* #param startElement
* #return event with namespace
*/
private StartElement withNamespace(StartElement startElement) {
List<Object> namespaces = new ArrayList<Object>();
namespaces.add(factory.createNamespace(namespaceURI));
Iterator<?> originalNamespaces = startElement.getNamespaces();
while (originalNamespaces.hasNext()) {
namespaces.add(originalNamespaces.next());
}
return factory.createStartElement(
new QName(namespaceURI, startElement.getName().getLocalPart()),
startElement.getAttributes(),
namespaces.iterator());
}
#Override
public XMLEvent nextEvent() throws XMLStreamException {
XMLEvent event = super.nextEvent();
if (event.isStartElement()) {
if (++startElementCount == 1) {
return withNamespace(event.asStartElement());
}
}
return event;
}
#Override
public XMLEvent peek() throws XMLStreamException {
XMLEvent event = super.peek();
if (startElementCount == 0 && event.isStartElement()) {
return withNamespace(event.asStartElement());
} else {
return event;
}
}
}
To see how this is used, let's copy some XML without namespace declaration to System.out using the event API:
StringReader xml = new StringReader("<?xml version='1.0'?><alice>bob</alice>");
XMLEventReader reader = XMLInputFactory.newInstance().createXMLEventReader(xml);
reader = new NamespaceAddingEventReader(reader, "http://foo");
XMLEventWriter writer = XMLOutputFactory.newInstance().createXMLEventWriter(System.out);
writer.add(reader);
writer.flush();
Running the code will print
<?xml version='1.0' encoding='UTF-8'?><alice xmlns="http://foo">bob</alice>

Spring Array with Strings

I'm working with some Java that I generate with JAXB but I don't think the JAXB is the problem since the structure of the code generated matches the getter and setter methods for Spring properties that now work but earlier on gave me this same type of exception.
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'previousCurrentEstateNo' of bean class [ca.qc.ic.osb.efilingClasses.EIS]: Bean property 'previousCurrentEstateNo' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
The difference here is the use of a String array. I've tried the various suggestions that are supposed to work without success. I'm using Spring 3.0.6.
<bean id="eisJointSummary" class="ca.qc.ic.osb.efilingClasses.EIS"
scope="prototype" lazy-init="true">
<property name="previousCurrentEstateNo" >
<list>
<value>1234</value>
</list>
</property>
</bean>
within EIS class:
public static class Estate
{
protected String[] previousCurrentEstateNo;
public String[] getPreviousCurrentEstateNo() {
if (this.previousCurrentEstateNo == null) {
return new String[ 0 ] ;
}
String[] retVal = new String[this.previousCurrentEstateNo.length] ;
System.arraycopy(this.previousCurrentEstateNo, 0, retVal, 0, this.previousCurrentEstateNo.length);
return (retVal);
}
public String getPreviousCurrentEstateNo(int idx) {
if (this.previousCurrentEstateNo == null) {
throw new IndexOutOfBoundsException();
}
return this.previousCurrentEstateNo[idx];
}
public int getPreviousCurrentEstateNoLength() {
if (this.previousCurrentEstateNo == null) {
return 0;
}
return this.previousCurrentEstateNo.length;
}
public void setPreviousCurrentEstateNo(String[] values) {
int len = values.length;
this.previousCurrentEstateNo = ((String[]) new String[len] );
for (int i = 0; (i<len); i ++) {
this.previousCurrentEstateNo[i] = values[i];
}
}
public String setPreviousCurrentEstateNo(int idx, String value) {
return this.previousCurrentEstateNo[idx] = value;
}
Thanks
You are creating a bean of the type ca.qc.ic.osb.efilingClasses.EIS and that class doesn't have a previousCurrentEstateNo property.
From what I can tell from the information you provided the previousCurrentEstateNo is a property of Estate.
I am assuming that EIS has a property of type Estate?
Try something to this effect:
<bean id="eisJointSummary" class="ca.qc.ic.osb.efilingClasses.EIS"
scope="prototype" lazy-init="true">
<property name="nameOfTheEstatePropertyInEIS">
<bean class="ca.qc.ic.osb.efilingClasses.EIS.Estate">
<property name="previousCurrentEstateNo">
<list>
<value>1234</value>
</list>
</property>
</bean>
</property>
</bean>

Windows Phone 7 Connect to SharePoint via SOAP

I am making my second application for the Windows 7 Phone Series platform and I cannot seem to connect to a SharePoint server using https.
99% of the following is not my code. I have borrowed it from http://blog.daisley-harrison.com/blog/post/Practical-Silverlight-and-SharePoint-Integration-Part-Two.aspx untill I can further understand how SOAP works in W7P Series.
I know that I need some way of sending credentials over but the win 7 API does not seem to let you.
ServiceReferences.ClientConfig
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ViewsSoap" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" transferMode="Buffered">
<security mode="TransportCredentialOnly"/>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://my.secureconnection.com/_vti_bin/views.asmx"
binding="basicHttpBinding" bindingConfiguration="ViewsSoap"
contract="SharePointListService.ViewsSoap" name="ViewsSoap" />
</client>
</system.serviceModel>
</configuration>
This is my maincode page:
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;
try
{
Uri serviceUri = new Uri("https://my.secureconnection.com" + SERVICE_LISTS_URL);
BasicHttpBinding binding;
if (serviceUri.Scheme == "https")
{
binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
}
else
{
binding = new BasicHttpBinding(BasicHttpSecurityMode.None);
}
EndpointAddress endpoint = new EndpointAddress(serviceUri);
ListsSoapClient listSoapClient = new ListsSoapClient(binding, endpoint);
NetworkCredential creds = new NetworkCredential("administrator", "iSynergy1", "server001");
//listSoapClient.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Identification;
//listSoapClient.ClientCredentials.Windows.ClientCredential = creds;
listSoapClient.GetListCollectionCompleted += new EventHandler<GetListCollectionCompletedEventArgs>(listSoapClient_GetListCollectionCompleted);
listSoapClient.GetListCollectionAsync();
}
catch (Exception exception)
{
handleException("Failed to get list collection", exception);
}
}
#region ShowExceptionDetail Property
public static readonly DependencyProperty ShowExceptionDetailDependencyProperty = DependencyProperty.Register("ShowExceptionDetail",typeof(bool),typeof(Page),new PropertyMetadata(true));
public bool ShowExceptionDetail
{
get { return (bool)GetValue(ShowExceptionDetailDependencyProperty); }
set { SetValue(ShowExceptionDetailDependencyProperty, value); }
}
#endregion
private void handleException(string context, Exception exception)
{
this.Dispatcher.BeginInvoke(delegate()
{
bool showExceptionDetail = this.ShowExceptionDetail;
string message = "";
Exception next = exception;
do
{
if (message.Length > 0) { message += ";" + Environment.NewLine; }
if (next.Message == null || next.Message.Length == 0) { message += next.GetType().FullName; }
else { message += next.Message; }
if (showExceptionDetail)
{
if (next.Data.Count > 0)
{
bool first = true;
message += " {";
foreach (string key in next.Data.Keys)
{
if (first) { first = false; }
else { message += ", "; }
message += key + "=\"" + next.Data[key] + "\"";
}
message += "}";
}
if (next.InnerException != next)
{
next = next.InnerException;
continue;
}
}
next = null;
}
while (next != null);
MessageBox.Show(message, context, MessageBoxButton.OK);
});
}
private const string SERVICE_LISTS_URL = "/_vti_bin/lists.asmx";
void listSoapClient_GetListCollectionCompleted(object sender, GetListCollectionCompletedEventArgs e)
{
try { myList.Text = e.Result.ToString(); }
catch (Exception exception) { handleException("Failed to get list collection", exception); }
}
}
When I run this and it gets to the "ListsSoapClient" part, it breaks. If you dig down into the error output it says access is denied. I have tried various methods of sending credentials but none seem to work. "ClientCredentials.Windows" is not supported and ClientCredentials.UsersName.Username is read only.
Microsoft has confirmed that NTLM is not supported yet in the SDK. http://social.msdn.microsoft.com/Forums/en-US/windowsphone7series/thread/43a84dff-9447-4e95-8040-8a5447514fa0
UPDATE
Looks like someone found a workaround http://zetitle.wordpress.com/2010/03/30/wp7-connecting-to-web-services-that-uses-authentication/

Resources