Spring-ws: Multiple endpoints/wsdl/xsd/you-name-it - xsd

Info: I'm using Spring-ws 1.5.9 and Spring 2.5.6
I'm currently in the process of build a lot of web services and have a few questions as to how the architecture should be.
Right now I have a single web service. It (of course) contains a single wsdl and a single endpoints and so forth.
I'm currently extending the web service, and there I have created another xsd, auto-gen code using JAXB2 (xjc) and so forth.
Now, how should I handle these xsds, wsdl(s), code and so forth? I cannot see what Spring-ws recommends...
My architect would like to have a single wsdl, which can be achieved using the following:
<bean id="schemaCollection" class="org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection">
<property name="xsds">
<list>
<value>one.xsd</value>
<value>two.xsd</value>
</list>
</property>
<property name="inline" value="true"/>
Is this a good way to do this? I'm gonna end up with like 10-15 web services thus a large wsdl.
How about endpoints? Should I create a single endpoint and test for the type of request (e.g. using instanceof)? I myself think that having one endpoint mapping to one request is more elegant/clean.
Finally, what about marshalling? I have this (with one ws/schema):
<oxm:jaxb2-marshaller id="marshaller" contextPath="mydomain.signals.one.v1_0.schemas"/>
<oxm:jaxb2-marshaller id="unmarshaller" contextPath="mydomain.signals.v1_0.schemas"/>
But, how should I add another schema to this?? I'm trying something like the following, which doesn't seem to be working for me right now:
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPaths">
<list>
<value>mydomain.signals.one.v1_0.schemas</value>
<value>mydomain.signals.two.v1_0.schemas</value>
</list>
</property>
</bean>
I hope this makes sense. What I'm aiming for is pointers and hints as to what I should do.

If you have 10-15 web services there's no way around not having a huge wsdl. If the goal is a single wsdl, what you are doing seems acceptable.
I would prefer endpoints for each request.
Also, have you tried using a colon separated list of values for your context path? So, don't use the list, just have one long string with each context path separated by colons.
From the Spring-WS documentation:
The context path is a list of colon (:) separated Java package names
that contain schema derived classes.
I know that passage is for Jaxb1 but I'm pretty sure it still applies to the Jaxb2Marshaller. I think you'd only use the list variant if you were specifying classes.
http://static.springsource.org/spring-ws/site/reference/html/oxm.html

Related

Understanding how an extension is wired up in SAP Commerce

I am working on the SAP Commerce (formally known as Hybris) ecommerice system.
The Warehousing extension is being added to a B2B site. Upon adding it, On the Stock Level item the Invoice Event collection is visable on the admin tab. An ATP Formula has been set on the Base Store. The stock is now displayed on the PDP. In an OTB site I have seen an OTB instance adjust the stock levels accordingly upon completing an order, but that is not happening on the local dev instance. The question is why?
Is the impression correct that some facade within the warehousing extension is called during the order-processing process? If so, how exactly is that wired up? There doesn't seem to be any relationship to the warehousing extension and any other code.
UPDATE 1:
Here is an example of the question: After adding a new product populator to the custom facade, a few entries are added to the *-spring.xml file, one of them being adding the populator to the configurablePopulatorModification. Finally the option needs to be added to the ProductOptions list in the controller. Then the populator is called when that controller is called.
In this example the connection between the controller and the popular is clear, once it is understood how things are wired up. There is a connection to the ProductOptions in the custom core extension, custom facade extension, and custom accelerator. Once someone knows how this is "wired up" it can be easily duplicated.
What I am trying to understand is this: The warehousing extension has been added to the localextensions.xml, but there is NO reference to any aspect of that anywhere else in the system, AT ALL. Somehow some extension between the storefront accelerator and the platform code has to know about the new functionality found in the warehousing extension so that it is called. How?????
UPDATE 2:
After adding the warehousing extension, there are new attributes added to existing itemTypes that show up in Backoffice. It is my understanding that this is the concept which Modifying Lists and Maps in Spring Context explains.
The issue I am having problems understanding is how the business logic within the warehousing extension is being called to modify the stock levels. My best guess is that the function doing the change is WarehousingStockLevelFacade.createStockLevelAdjustements(...). I have searched high and low for where createStockLevelAdjustements(...) is called and it is ONLY called in the warehousingwebservices.
I am at a total loss on how exactly any of the facades wihtin warehousingfacades or warehousingwebservices is being called by
Hmmm, your text contains more than one question I think. So I try to answer each part of them separately.
In an OTB site I have seen an OTB instance adjust the stock levels accordingly upon completing an order, but that is not happening on the local dev instance
There should be no difference on the systems. You should always look, that you have the same configuration on each system. Normally the 'config' folder here is the part where you define the configuration. From system to system there can be small difference. But for example, the 'localextensions.xml' shold always be the same.
Is the impression correct that some facade within the warehousing extension is called during the order-processing process?
No. You define your extensions in the 'localextensions.xml' and than the new parts are on any system. Have you done an 'UPDATE' on each system, so that the new types are also imported in the type system and the database?
So overall. You define your extensions. And than hybris includes all needed extensions automatically. You can see this, when you start the server, which extensions are loaded.
UPDATE 1
I think, now I got your point. I try to stay in common and not to specify on the 'warehouse' extension. Hybris has some funtionalities how to modify code 'afterwards'. Here are some useful links
Modifying Spring beans afterwards
Extension Dependency
Also have a look left in the navigation about the 'Extnsion Concept'. Maybe some points will than be clear.
So in your example, think what happens is: first new attributes in the *-items.xml, than there will be a 'modifiyPopulatorList' bean somewhere.
UPDATE 2
I don't know the 'warehousing' extension. But I think there must be a part that overwrites the 'normal' beans with the 'warehousing' beans. Something like:
<bean id="stockLevelBean" ...>
<property name="normalProvider" ref="normalProvider"/>
</bean>
<bean id="stockLevelBean" ...>
<property name="warehousingProvider" ref="warehousingProvider"/>
</bean>

Modelling Cassandra from XML & C#

I am very beginner to Cassandra. I am finding it difficult to model the XML file attached.
My requirement is:
I get many XML files as given below on daily basis. I need to write a C# program to read the XML and store in Cassandra.
Once stored, the data would be read by 1000's of customers 1000's of times. Once the data is stored, it would NOT be updated again.
NOTE: It is possible that each parent node (Ex: Customer/Site...) may appear more no. of times. i.e i may have Customer2, Site2, another EquipmentDetails node etc.
My XML:
<?xml version="1.0" standalone="yes"?>
<MyAnalystXMLReport>
<MC-DomainID ID="XYZ123">
<Customer Name="CUSTOMER1" ID="53043">
<Site Name="SITE1" ID="488688">
<EquipmentDetails>
<EquipmentDescription>Test Desc</EquipmentDescription>
<EquipmentRefId>T3567111</EquipmentRefId>
<ComponentDescription>COM Oil</ComponentDescription>
<ComponentRefId>
</ComponentRefId>
<AnanlystNo>1235LKJU</AnanlystNo>
<ComponentType>TestComp</ComponentType>
<Sample SampleNo="976023696">
<SampleCondition>USUAL</SampleCondition>
<AnalysisComments>Test Comments</AnalysisComments>
<DateRecieved>2015-12-10</DateRecieved>
<DateAnalysed>2015-12-18</DateAnalysed>
<EquipmentLife>
</EquipmentLife>
<LubricantLife>
</LubricantLife>
<TopUpVolume>0</TopUpVolume>
<FuelUsed>
</FuelUsed>
<Tests>
<TestGroup Name="Group NAME1" ID="667">
<Test Name="Test Name1" ID="1785">
<Result>171.3</Result>
</Test>
</TestGroup>
<TestGroup Name="Group NAME2" ID="617">
<Test Name="Test NAME2" ID="1763">
<Result>153.40</Result>
</Test>
</TestGroup>
</Tests>
</Sample>
</EquipmentDetails>
</Site>
</Customer>
</MC-DomainID>
</MyAnalystXMLReport>
How would i model this XML in efficient way to achieve this requirement?
And what is the easiest way to store this data data & model in Cassandra using C#. Any example would be greatly appreciated.
Thanks for your help.
So to begin, modelling data for use in Cassandra is a bit different than a traditional RDBMS. My first suggestion would be to look at this link:
http://www.datastax.com/dev/blog/basic-rules-of-cassandra-data-modeling
Basically Cassandra using a table-per-query methodology to determine the data models. This means that you need to know how your application will query the data and then model your logical and physical persistance models after that. DataStax has some excellent tutorial videos on Cassandra in general and Data modelling specifically. See here:
https://academy.datastax.com/courses/ds220-data-modeling
As far as how to use it from C#, there is a good video on how to get started using c# here:
https://academy.datastax.com/demos/getting-started-apache-cassandra-and-c-net

CombinedResourceHandler excluded resources doesn't recognize resources with query string

I have a couple of CSS files that I don't want to combine, but I also want to bust cache for those resources, so I declared them with:
<h:outputStylesheet name="css/styles.css?version=#{startup.time}" />
It was working fine until I added the CombineResourceHandler. Now the new handler does not recognize the name of the resource, and I cannot use a wildcard to exclude those resources, something like:
<context-param>
<param-name>org.omnifaces.COMBINED_RESOURCE_HANDLER_EXCLUDED_RESOURCES</param-name>
<param-value>css/styles.css*</param-value>
</context-param>
If I remove the version parameter I have to do versioning of those files, which is something I would like to avoid.
Any ideas on how to implement this the easiest way?
OmniFaces identifies resources by the internal ResourceIdentifier class. It didn't take into account any query strings, path parameters nor path fragments. As per this commit, this has been fixed. The fix is available in today's latest 2.2-SNAPSHOT.
Support for wildcard pattern in excluded (and suppressed) resources context param would be a good candidate for a feature request.

I need my BizTalk map to stop converting xml:lang to ns1:lang

I have a map in BizTalk 2009 that is converting some data into an XML document to be sent on to another system. The target schema includes some elements with xml:lang attributes. BizTalk generates those as ns1:lang. The target system requires that the prefix xml be used.
Here is a simplified example to show what BizTalk is doing:
sample.xsd
<xs:schema targetNamespace="http://example.com/"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="common.xsd"
namespace="http://www.w3.org/XML/1998/namespace" />
<xs:element name="example">
<xs:complexType>
<xs:attribute ref="xml:lang" />
</xs:complexType>
</xs:element>
</xs:schema>
common.xsd
<xs:schema xmlns:xml="http://www.w3.org/XML/1998/namespace"
targetNamespace="http://www.w3.org/XML/1998/namespace"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:attribute name="lang" type="xs:language" />
</xs:schema>
Example of map output
<ns0:example xmlns:ns0="http://example.com/"
xmlns:ns1="http://www.w3.org/XML/1998/namespace"
ns1:lang="en-US" />
Is there some way to convince BizTalk to use the xml prefix?
As far as I know, there is no builtin way for achieving this.
There are, however, two solutions that I can see:
Use a Custom XML StyleSheet
If you right-clik on the map and look carefully in the generated xsl stylesheet, you'll see a XML namespace declaration like this:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="http://www.w3.org/XML/1998/namespace"
...
>
...
<xsl:attribute name="ns1:lang">
...
This is the default behaviour of the BizTalk mapper and you cannot do anything about it. However, if you proceed to extract the generated XSLT and use this as the backend for your map, you can change this declaration to match the expected outcome.
First, copy the stylesheet to the location of your project.
Include this stylesheet as a file in your BizTalk project
Update the stylesheet, so that the namespace declaration and the matching attribute prefix are correct.
The resulting xsl stylesheet looks like this:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
...
>
...
<xsl:attribute name="xml:lang">
...
Now you can use this custom stylesheet as a backend for the map.
In Visual Studio, open the map.
Click anywhere on a blank space in the BizTalk designer surface.
In the map properties, locate the Custom XSL Path and specify the location of your custom stylesheet.
Use a Custom Pipeline Component
What you're after is that the message is correct for your target recipient. So the idea is to change the offending namespace prefix as part of sending the message outside BizTalk. The transformation happens during the processing of the send pipeline.
Nic Barden has blogged and provided some source code about this here. You can use his sample as the basis for performing replacement of namespace prefixes, rather than replacing namespaces themselves.
I strongly encourage you to check out the whole series of posts he's done about Developing Streaming Pipeline Components. Nic has made an extensive and thorough job of describing all that's needed to author robust and enterprise-class pipeline components.
Part 1
Part 2
Part 3
Part 4
Part 5
The easier way to do it and have everything work is to just add the namespace declaration at the beginning of the schema definition like this.
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xml="http://www.w3.org/XML/1998/namespace">
<xs:import schemaLocation="xml.xsd" namespace="http://www.w3.org/XML/1998/namespace" />
In addition to Maxime's suggestions, here are the other possibilities I've found:
Ignore it and hope that the vendor’s API will take it.
I don’t think this will work. When I test the map, BizTalk gives me this error:
Output validation error: Prefix 'ns1' cannot be mapped to namespace name reserved for "xml" or "xmlns".
Hello, BizTalk!? You’re the one who decided to use ns1. Don’t complain about it to me!
Use an XSL-based script functoid to force the output.
This is based on the suggestion I received on the BizTalk forums. It requires that we fudge the output schema to use a dummy attribute that gets replaced with the xml:lang attribute by the functoid.`
Add a search/replace expression
Take the orchestration that calls the map and add an expression after it that would take the XML we’re sending to the vendor and run it through a search/replace regex to fix the namespace prefixes.

SPWeb.ProcessBatchData() create strange folder name in sharepoint document library

i am using SPWeb.ProcessBatchData() method to batch create folders inside one document library. everything works fine expect after folders have been created, folders all have very strange name. for example if my document library's name is 000, then the folder name's is "1._000". I tried a lot of other properties, but i have no luck to find out how to set the folder name right. Can some one help me on this?
Cheers
You are right about the webservices are a bit more strict on the characters you can put in and it cannot process the same amount of requests, but you can work around that I guess :)
What you can do though if you really want to use the ProcessBatchData method is, re-use the result you receive back from the method. If it's correct, you will get all the ListItemId's back from each folder. Using the Id's you can create another batch to rename the Title's of the items.
But if I were you, I would switch and use the webservice and workaronud that :)
this is the correct syntax of the XML to create a folder truly titled:
<?xml version="1.0" encoding="utf-8"?>
<ows:Batch OnError="Continue">
<Method ID="Test">
<SetList Scope="Request">82d62a9a-55ba-49c8-a9b8-68ec965a5931</SetList>
<SetVar Name="Cmd">Save</SetVar>
<SetVar Name="ID">New</SetVar>
<SetVar Name="Type">1</SetVar>
<SetVar Name="owsfileref">/sites/1/docs/folder1</SetVar>
</Method>
</ows:Batch>
the critical line is this one:
<SetVar Name="Type">1</SetVar>
"Type" is the accepted alias of the FSObjType field
Regards,
Ahmad

Resources