CruiseControl.NET Preprocessor 'include' Anomaly - include

Here's a strange one relating to a combination of the 'define' and 'include' functionality that the CC.NET preprocessor exposes. We're running CCNet 1.4.4.83, and our ccnet.config file is structured and split to make best use of common element blocks stored in subfiles that are included by the main config file; we also split out the core project definitions into their own include files too, leaving ccnet.config as essentially a series of includes thus:
<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
<!-- Configuration root folder - defined so we can use it as a symbol instead of using slightly confusing relative paths -->
<cb:define ccConfigRootFolder="C:\CruiseControl.NET\Config"/>
<!-- Globals - standard or shared build elements common to all projects -->
<cb:include href="$(ccConfigRootFolder)\Globals\globals.xml" xmlns:cb="urn:ccnet.config.builder"/>
<!-- CruiseControl.NET Configuration - refresh configuration if changed -->
<cb:include href="$(ccConfigRootFolder)\CCNet Configuration\ccnet_configuration.xml" xmlns:cb="urn:ccnet.config.builder"/>
<!-- Project #1 -->
<cb:include href="$(ccConfigRootFolder)\Project1\project1.xml" xmlns:cb="urn:ccnet.config.builder"/>
<!-- Project #2 -->
<cb:include href="$(ccConfigRootFolder)\Project2\project2.xml" xmlns:cb="urn:ccnet.config.builder"/>
</cruisecontrol>
This works a treat - the preprocessor correctly includes and parses the <define> elements in globals.xml (and recursively parses further files included from globals.xml too) and the projects included afterwards (which contain references to those defined elements) are parsed correctly.
To further refine ccnet.config in an attempt to reduce the possibility of mistakes breaking the build process, we altered it to look like this:
<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
<!-- Configuration root folder -->
<cb:define ccConfigRootFolder="C:\CruiseControl.NET\Config"/>
<!-- Project 'include' element definition -->
<cb:define name="ProjectInclude">
<cb:include href="$(ccConfigRootFolder)$(ccIncludePath)" xmlns:cb="urn:ccnet.config.builder"/>
</cb:define>
<!-- Include common gobal elements -->
<cb:ProjectInclude ccIncludePath="\Globals\globals.xml"/>
<!-- Project #1 -->
<cb:ProjectInclude ccIncludePath="\Project1\project1.xml"/>
<!-- Project #2 -->
<cb:ProjectInclude ccIncludePath="\Project2\project2.xml"/>
</cruisecontrol>
As you can see, we embedded the common, repeated, part of the 'include' definition in it's own defined block, and then use that to effect each include using the path as a parameter - the idea being that future modifiers of the file won't have the opportunity to accidentally forget something on their new included project lines (such as the preprocessor URN); as long as their xml file exists and they get the path to it right, the rest is taken care of in the common include definition.
The only problem is that this doesn't work - for some reason, it looks like the globals.xml file isn't being parsed properly (or maybe even included) because the projects included after it complain of not having elements defined; that is, references to elements defined in the globals file don't appear to have been 'registered', because the projects don't recognise them.
We've tried taking out the nested includes from globals.xml and including them directly at the top level, to no avail. Commenting-out the first troublesome element reference in the project just causes Validator to complain about the next one, with message "Preprocessing failed loading the XML: Reference to unknown symbol XXXXX". If we embed the body of globals.xml into ccnet.config, however, this works. Bizarre though it may sound, it's as though the preprocessor is utterly failing to parse globals.xml but then happily chewing through the project files, only to then fail because the global references aren't defined.
Validator is failing silently if this is the case, however. And of course because it can't parse the project XML properly, we get nothing in the 'Original' or 'Processed' tabs either. The CruiseControl.NET Service itself fails to start with an unhelpful exception:
Service cannot be started.
System.Runtime.Serialization.SerializationException:
Type
'ThoughtWorks.CruiseControl.Core.Config.Preprocessor.EvaluationException'
in Assembly
'ThoughtWorks.CruiseControl.Core,
Version=1.4.4.83, Culture=neutral,
PublicKeyToken=null' is not marked as
serializable. Server stack trace: at
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object
obj, ISurrogateSelector
surrogateSelector, StreamingContext
context, SerObjectInfoInit
serObjectInfoInit, IFormatterConverter
converter, ObjectWriter objectWriter)
at
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object
obj, ISurrogateSelector
surrogateSelector, StreamingContext
context, SerObjectInfoInit
serObjectInfoInit, IFormatterConverter
converter, ObjectWriter objectWriter)
at
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object
graph, Header[] inHeaders,
__BinaryWriter serWriter, Boolean fCheck) at
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Ser...
All the documentation says this should work, and there's no mention of any incompatibility or inconsistency when using 'include' inside a 'define'. So I'm stumped, and any insight or advice would, at this stage, be highly regarded.

we're working on solving this issue for the 1.5 release (hopefully end this month)
http://jira.public.thoughtworks.org/browse/CCNET-1865
with kind regards
Ruben Willems

CCnet 1.5 Final has been released, so this gives you the excuse to test it:-)
If the problem still persists, you can also contact me via the ccnet lists.
http://groups.google.com.ag/group/ccnet-user or
http://groups.google.com.ag/group/ccnet-devel

Related

SFCC: Is there a way to automatically remove custom attribute definitions

We have a pretty old project where we have a lot of custom attribute definitions but do not trust our sites/site_template/meta/system-objecttype-extensions.xml to be complete.
Does anybody know of a way to remove a defined set of custom attribute definitions automatically? We can identify quite a lot that are definitely not used anymore but I'm missing the DELETE import functionality available for other types of data in SFCC.
Tx a lot for your help!
What to do, so I wrote my own parser / analyser / merger: https://github.com/Andreas-Schoenefeldt/SFCCAnalyser#combine-and-analyse-system-objecttype-extension-xml-files
It can be used like this:
put all xml files you would like to merge into one in ./data/meta-xmls/
run node combine-xml.js
the resulting merged and cleaned xml file will be in ./data/meta-xmls/combined.xml
The resulting file will contain all custom attribute definitions accross the systems, so it can then safely imported checking the Delete existing attribute definitions and attribute groups not contained in the import file, including attribute definitions marked as "externally-defined".

XMLSchema namespace is ignored (JAXB unmarshal fails)

I'm trying to unmarshal a complex payload for which I do not have a complete definition (just the wrapper, which then defines the actual varying content as
#XmlAnyElement(lax = true)
protected Object any;
Now, I've done this before in another project and it worked just fine, in a two step unmarshal - first do the wrapper, then access any as a Node and unmarshal that to the expected content (for which I had no xsd and I had to manually model into classes)
This time however, the content comes back namespaced and the only way I've gotten it to work is to add namespace to every XmlRootElement, XmlElementand XmlType in all of my own modeled structures. Obviously this is a huge pain and I tried to add an XmlSchema to the package that holds the domain objects mapping the Xml payload, but for some reason that is not picked up by the unmarshaller.
#javax.xml.bind.annotation.XmlSchema(namespace = "http://mynamespace.com",
elementFormDefault = XmlNsForm.QUALIFIED)
package com.myproject.schema;
I've tried creating unmarshallers in multiple ways, none pick-up the XmlSchema in the package
val marshaller = Jaxb2Marshaller()
marshaller.setPackagesToScan("supplier.package", "com.myproject.schema")
or
val unmarshaller = JAXBContext.newInstance(myKClass.java).createUnmarshaller()
My (relevant) dependecies look like this
implementation("org.springframework.boot:spring-boot-starter-webflux:2.4.1")
implementation("org.springframework.ws:spring-ws-core:3.0.10.RELEASE")
implementation("javax.xml.bind:jaxb-api:2.3.1")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.10.1")
EDIT:
So apparently the package-level annotation is not read because the package-info.java file seems to be excluded from the build (and so it's not picked up by the classloader). I've looked at the classes build from the xjc output and those do contain the package-info.
I'm still looking into why this is happening, maybe there's a flag for Gradle or the Kotlin plugin I can switch to get that included.
Problem is fixed indeed by a package-level XmlSchema annotation. However, one must check that it is indeed picked-up when the class is loaded (reflection is your friend) and if not, keep in mind that package-info.java files must be put in your Java sources and not your Kotlin sources (seems obvious, but it's not always as obvious when you're a few hours down the rabbit hole).

Add setShouldAppendNewLine to FileWritingMessageHandler in Spring Integration

I'm using Spring Integration 4.1.0.
I have a use case where I'd like to produce a single file that will contain a row for each message that flowed to a channel.
Shown below is the config to do that, as per the "Define an integration flow" section of this link: https://spring.io/guides/gs/integration/
<feed:inbound-channel-adapter id="news" url="https://spring.io/blog.atom">
<int:poller fixed-rate="5000"/>
</feed:inbound-channel-adapter>
<int:transformer
input-channel="news"
expression="payload.title + ' # ' + payload.link + '#{systemProperties['line.separator']}'"
output-channel="file"/>
<file:outbound-channel-adapter id="file"
mode="APPEND"
charset="UTF-8"
directory="/tmp/si"
filename-generator-expression="'SpringBlog'"/>
This seems like a fairly common use-case (at least in my team it certainly is). You'll note that the CharacterStreamWritingMessageHandler (for writing to stdout and stderr) offers the this setter setShouldAppendNewLine(boolean shouldAppendNewLine). Could a similar setting be offered on the FileWritingMessageHandler?
A point could be made to say that is really the job of a transformer (as is shown in the example), however if it's being offered already as a setting on the CharacterStreamWritingMessageHandler class then a decision was made to combine this special transformer use-case on that class and I see this as a reasonable request to make FileWritingMessageHandler behave similarly. Also with SpEL expressions not necessarily running as fast as compiled code (unless we use the new spring.expression.compiler.mode=MIXED setting) this would save on some processing time as the transformer step would not be needed.
This seems like a reasonable request to me (given the existing precedent on the stream adapters), especially when writing in APPEND mode.
Please open a 'new feature' JIRA Issue.
Even better, consider contributing!
We generally don't make schema changes mid-stream in point releases (e.g. 4.1.1) so the XML namespace support would have to be deferred until 4.2.
However, adding the property to the class would enable it to be set when using Java #Configuration, or by getting a reference to the handler and setting it during application initialization.

.NET VisualStudio wsdl multiple xsd files, overlapping definitions

I'm writing an implementation for a mailing service and I'm having trouble with the code that VisualStudio autogenerates from the wsdl file. The API contains several versions of the same objects. The objects are defined in separate xsd files corresponding to a particular version:
Although each xsd file defines a specific namespace, the complex element names are the exact same in all xsd files:
This causes VisualStudio to assign arbitrary names to the classes representing the complex names to retain uniqueness:
If you look at the xsd files, OpenMailingGroup_13B returns an OpenMailingGroupResponse and OpenMailingGroup_15A also returns an OpenMailingGroupResponse, and IMHO that's ok from a definition point of view because they are defined in separate xsd files each having its own separate namespace. However, when VisualStudio generates the proxy classes, it names the return type of OpenMailingGroup_13B as OpenMailingGroupResponse2 and the return type of OpenMailingGroup_15A as OpenMailingGroupResponse4.
This becomes an issue when you update the web service reference and new versions are added and removed (e.g. a new OpenMailingGroup_17X now exists). The problem is that VisualStudio would now use a different naming for the OpenMailingGroupResponse. What was OpenMailingGroupResponse4 for OpenMailingGroup_15A could not be OpenMailingGroupResponse9. And that breaks our code.
We thought of a few possible solutions:
Writing adapter classes - but there are literally hundreds of classes and that would be too painful.
Using var in the variable definition in order not to hardcode the type, but there's lots of nesting involved (e.g. a complex type has another complex type which has another complex type, etc.).
Not update the wsdl...
So, my question is: can I tell VisualStudio to split the generated code into multiple .NET namespaces, each corresponding to its xsd file? Maybe a general question is: is there anything I can do about this?
Thanks in advance,
Tiberiu

JAXB generated enums when invoked through wsdl2java

This is a follow-up question to JAXB enumeration with numeric values. A more thorough explanation can be found at http://blog.bdoughan.com/2011/08/jaxb-and-enums.html, which links back to that posting. I will be using Blaise's blog posting as a starting point. It was very useful, thank you.
When I call xjc as shown on the blog and pass it the XSD file and the bindings file, the generated types are the same as shown on the blog, i.e. as required. Well and good.
But my Maven build does not invoke xjc directly on my set of XSD files; it invokes wsdl2java on my WSDL files, which include my XSD files. I can pass the -b parameter to xjc through the wsdl2java invocation (http://cxf.apache.org/docs/maven-cxf-codegen-plugin-wsdl-to-java.html, example 7), and when I do that, the enum type is generated correctly according to the bindings file but the field that uses it --- Person.educationLevel in the example at http://blog.bdoughan.com/2011/08/jaxb-and-enums.html --- has type String, not EducationLevelType as it should.
I have also tried using an inline customization instead of an external binding file, i.e. decorated the education-level-type simpleType element in the XSD file with
<annotation>
<appinfo>
<jxb:typesafeEnumClass>
<jxb:typesafeEnumMember value="1-6" name="ONE_TO_SIX"/>
<jxb:typesafeEnumMember value="6-12" name="SIX_TO_TWELVE"/>
...etc...
</jxb:typesafeEnumClass>
</appinfo>
</annotation>
and this works nicely, even when used through wsdl2java: the enum is generated correctly, and the field has type EducationLevelType.
However, we do not own the XSD files so using an inline customization is not an option.
So, how do I make this work?
Any help is much appreciated.

Resources