XMLSchema namespace is ignored (JAXB unmarshal fails) - spring

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).

Related

Does serialization of objects with same class but different packages cause an errors in Axon?

I read a blog post and there was a sentence like this
"In Axon, there are constraints that require the package structure of the Event classes to be identical.
So even the same class, if the package is different, an error can occur."
And for this reason, he recommends using a multi-module structure.
is that true? I'm looking at the references and trying to find something like this, but I can't.
This point is indeed true, #YongD.
Axon Framework, when serializing any of your objects, will store the serialized format and the type. The serialized format that's stored most often is a byte[] of either XML or JSON. Which of the two depends on whether you have configured the XStreamSerializer or the JacksonSerializer.
So next to the serialized data, we have the type. The type, by default, would be the fully qualified class name and an optional revision number. Without the fully qualified class name, the serializer wouldn't know how to deserialize your data back into the required format. The package name is part of the FQCN, having different package names for conceptually the same class might cause issues upon deserialization.
This is why in sample projects provided by AxonIQ, you will always see all the messages belong to a core-api or api package or module. Already having this separation will allow for easier extraction of services into microservices at a later stage.

How to process JSON plugin config with structs not known at compile-time

I am working with a Go-based software that allows to use several plugins.
A plugin can't be used twice (by choice) => a plugin is either enabled or disabled
Plugin names are unique
All plugins are configured with a plugin-specific configuration defined as JSON-serializable struct
The use of plugins is controlled using a single configuration. Consider the following simplified example of the configuration struct:
type PluginConfig struct {
PluginA *PluginA `json:"pluginA,omitEmpty"`
PluginB *PluginB `json:"pluginB,omitEmpty"`
PluginC *PluginC `json:"pluginC,omitEmpty"`
PluginD *PluginD `json:"pluginD,omitEmpty"`
}
Somewhere in the code, each of the fields is checked, and the actual plugin added if configuration was provided:
if config.PluginA != nil {
AddPlugin(plugina.New(config.PluginA))
}
if config.PluginB != nil {
AddPlugin(pluginb.New(config.PluginB))
}
// ...
I am trying to rework the software so external plugins are supported as well. The software is required to still function as before, so the format and way of configuration cannot be changed. Additionally, I am required to use the default encoding/json package for unmarshaling the configuration.
If I knew all plugins at compile-time, I could go generate the code of the configuration struct before compiling, and generate the corresponding if config.SomePlugin { } statements as well. While this might even be of good performance because no dynamic lookup is used, I would be still limited to knowing all plugins in advance. If this was the case, would you agree this approach is a valid way to go?
What could I do if I could only get a list of plugins at runtime? How could I process the configuration file then, so not only the plugin names are dynamic, but I would also not know of the specific configuration before?
You have two options:
Unmarshal to a generic type such as map[string]interface{}
Unmarshal to json.RawMessage
In either case, you can then pass that data to the plugin, once it's loaded, to do full unmarshaling/conversion.

Cannot Access SysML stereotypes and their properties in Acceleo

I am developing a M2T generator in Acceleo (in Eclipse). The model is basically a UML model with SysML profile created in Papyrus. It includes Blocks and FlowPorts. I have to access these stereotypes but it seems that I cannot retrieve any SysML object even though they appear in list (code suggestion). Actually I have to access ‘Direction’ property of FlowPort associated with Port. I have already tried suggestions and answers from various forums (including https://www.eclipse.org/forums/index.php/t/452587/) but in vain.
The code is given below. I have created java services as suggested by https://www.eclipse.org/forums/index.php?t=msg&th=1060450&goto=1693765& but port.hasStereotype(‘FlowPort’) always return false. I have also tried ‘SysML::PortAndFlows::FlowPort’ instead of ‘FlowPort’. I use Acceleo 3.6.2 on Eclipse Mars.
...
[template public generateElement(model : Model)]
[comment #main/]
[file ('created.txt', false, 'UTF-8')]
[for(port: Port | model.eAllContents(Port))]
[if(port.hasStereotype('FlowPort'))]
OK
[else]
NOT OK
[/if]
[/for]
[/file]
[/template]
I include following metamodels in the Module at the time of creating the module:
http://www.eclipse.org/uml2/5.0.0/UML
http://www.eclipse.org/papyrus/0.7.0/SysML
http://www.eclipse.org/papyrus/0.7.0/SysML/Blocks
http://www.eclipse.org/papyrus/0.7.0/SysML/Constraints
http://www.eclipse.org/papyrus/0.7.0/SysML/PortAndFlows
http://www.eclipse.org/emf/2002/Ecore
Also, I do register required packages including following in registerPackages() of Generate.java as suggested by the link just mentioned above.
// UML2 profiles
URI uri = URI.createURI("platform:/plugin/org.eclipse.uml2.uml.resources");
uriMap.put(URI.createURI(UMLResource.LIBRARIES_PATHMAP), uri.appendSegment("libraries").appendSegment(""));
uriMap.put(URI.createURI(UMLResource.METAMODELS_PATHMAP), uri.appendSegment("metamodels").appendSegment(""));
uriMap.put(URI.createURI(UMLResource.PROFILES_PATHMAP), uri.appendSegment("profiles").appendSegment(""));
// SysML profiles
uri = URI.createURI("platform:/plugin/org.eclipse.papyrus.sysml");
uriMap.put(URI.createURI(SysmlResource.LIBRARIES_PATHMAP), uri.appendSegment("librairies").appendSegment(""));
uriMap.put(URI.createURI("pathmap://SysML_PROFILES/"), uri.appendSegment("SysML.profile.uml").appendSegment(""));
uriMap.put(URI.createURI("pathmap://SysML_PROFILES/"), uri.appendSegment("model").appendSegment(""));
Any sort of help is appreciated.
I had an identical problem, but with UML/MARTE rather than SysML.
I bet that port.getAppliedStereotypes() always returns the empty list, no matter what (even if of course, port is stereotyped). I also tried everything you did, unsuccessfully, including double-checking if there was a #generated NOT in the javadoc of the registerPackages method (to it being re-generated each time).
I fixed the issue whit a little workaround. I assume that you (like I did) use as input for the transformation the model.uml file generated by Papyrus. This might actually be the cause of the problem, even though I don't see an alternative. If you open that file with a text editor, you'll find that the <FlowPort> tags are outside the <uml:Model> tag. This means that, for reasons that I still fail to understand, the stereotype() methods cannot "see" the stereotypes and always return null, or empty lists. This is possibly because they fail to match the stereotype base_NamedElement to the xmi:id inside the <uml:Model> tag.
On the other hand, if you define a template which takes as input a FlowPort (rather than a Model) you will be able to get your stereotyped element and all of its properties.
[template public generateElement(aFlowPort: FlowPort)]
[comment #main /]
[comment here you can access to the aFlowPort fields]
[/template]
Among others, you can also access the base_NamedElement property of the stereotype (i.e., the Port that is stereotyped FlowPort in your model), and you can use the qualifiedName property of the base element to map back the stereotype to the Port in your Model. In practice, this means that you have to link the stereotypes to their stereotyped entities by hand.
Clunky and annoying, but still gets the job done until somebody comes with a less "workaroundy" solution.

HOCON: multiple reference.conf resolution issue

I have multi-module project under SBT.
Project A (library) has reference.conf file with A's configuration parameters. Project A depends on akka-actor library, which ships with its own reference.conf file. Project A redefines some akka's parameters in own reference.conf.
Project B depends on A.
When I call ConfigFactory.load() in B, I'm getting wrong order of reference.confs merging. It first takes A's config, then applies akka-actor's config over it. Eventually, I'm getting initial akka-actor's configuration.
How can I fix it? I need to get akka-actor's config loaded first, then my A's config should be applied over it.
Ok, looks like I've found the answer in sources of ConfigFactory.
All the reference.conf is being loaded through ClassLoader.getResources. It returns java.util.Enumeration[URL]. The order of URLs in this enum is the answer to the question. So all you need to do: ensure the order of your reference.conf resources in this enumeration properly arranged.
Here is an example of how to do that. First, create your own version of ClassLoader by overriding getResources method:
import scala.collection.JavaConverters._
class CustomClassLoader(loader: ClassLoader) extends ClassLoader(loader){
override def getResources(name: String): util.Enumeration[URL] = {
val resources = super.getResources(name).asScala.toList
// arrange resources as you wish here
java.util.Collections.enumeration(resources.asJava)
}
}
Last, call load method of ConfigFactory with your CustomClassLoader instance.

What is the opposite of JAXB? i.e. generating XML FROM classes?

I am currently designing a solution to a problem I have. I need to dynamically generate an XML file on the fly using Java objects, in the same way JAXB generates Java classes from XML files, however the opposite direction. Is there something out there already like this?
Alternatively, a way in which one could 'save' a state of java classes.
The goal I am working towards is a dynamically changing GUI, where a user can redesign their GUI in the same way you can with iGoogle.
You already have the answer. It's JAXB! You can annotate your classes and then have JAXB marshal them to XML (and back) without the need to create an XML schema first.
Look at https://jaxb.dev.java.net/tutorial/section_6_1-JAXB-Annotations.html#JAXB%20Annotations to get started.
I don't know, if this is exactly what you're looking for, but there's the java.beans.XMLEncoder:
XMLEncoder enc = new XMLEncoder(new FileOutputStream(file));
enc.writeObject(obj);
enc.close();
The result can then be loaded by XMLDecoder:
XMLDecoder dec = new XMLDecoder(new FileInputStream(file));
Object obj = dec.readObject();
dec.close();
"generate xml from java objects:"
try xtream.
Here's what is said on the tin:
No mappings required. Most objects can be serialized without need for specifying mappings.
Requires no modifications to objects.
Full object graph support
For saving java object state:
Serialization is the way to do this in Java

Resources