I have a binding from a source XML file to a model in JAXB objects. Source XML looks for example like this:
<school>
...
</school>
After some processing my data model is nested like e.g. this
schoolX
courseA
student1
courseB
student1
When I call binder.updateXml(school), even though student1 is assigned to both instances of Course in my JAXB objects, it will in the XML only be placed in courseB.
Is this the normal behavior if student1 is assigned to multiple courses?
When I use a cloned student1 for one of the courses everything works as expected.
My bindings look like this:
<java-type name="School">
<java-attributes>
<xml-element java-attribute="courses" xml-path="course/" type="my.model.Course" container-type="java.util.List"/>
</java-attributes>
</java-type>
<java-type name="Course">
<java-attributes>
<xml-element java-attribute="students" xml-path="student/" type="my.model.Student" container-type="java.util.List"/>
</java-attributes>
</java-type>
<java-type name="Student">
<java-attributes>
<xml-element java-attribute="name" xml-path="#name"/>
</java-attributes>
</java-type>
Wrt Binder a JAXB implementation considers that there is a 1-to-1 relationship between objects and nodes. You can see this in the following methods:
http://docs.oracle.com/javase/7/docs/api/javax/xml/bind/Binder.html#getXMLNode(java.lang.Object)
http://docs.oracle.com/javase/7/docs/api/javax/xml/bind/Binder.html#getJAXBNode(XmlNode)
This is why you are running into issues when you have the same instance in two locations. For Binder a JAXB implementation expects these two instances to be different. This requirement doesn't exist when Marshaller is used.
Related
In my XSOData service I have an entity based on calculation view with input parameters. I can to set these parameters as constants in my XML view, i.e.
<List items="{dicts>/AncParams(p_dict_name='GROUPS',p_rec_id=2)/Results}" >
<StandardListItem
title="{dicts>NAME}"
/>
</List>
and it will work fine.
But how I can set parameters p_dict_name and p_rec_id dynamically? I tried to use expression bindings to get values for parameters from another model (something like this: <List items="{= ${dicts>/AncParams(p_dict_name='GROUPS',p_rec_id=${DictUIProps>/parentId})/Results} }" >) but with no luck. As I understand, expression bindings won't work. Is there any other way?
As far as I'm aware you can't do the aggregation binding dynamically through XML. At least not in the versions I have used and I have to admit I haven't re-checked in a while. The string never gets interpreted for inner bindings before it's applied to the model.
The way I do this is through the controller:
<List id="myList" />
and in your controller (onBeforeRendering or onPatternMatched or wherever your model and view are known to the controller):
this.getView().byId('myList').bindItems({
model: 'dicts',
path: `{/AncParams(p_dict_name='${p_dict_name}',p_rec_id=${p_rec_id})/Results}`,
template: new sap.m.StandardListItem({
title: '{dicts>NAME}'
})
});
you can use the getModel('dicts').createKey function to generate the path name which is a little cleaner I suppose.
This is the way to apply dynamic filters as well, In case you ever build those.
I inherited an OData service that exposes - among other things - a type called Evaluation. This type contains a lot of primitive type properties (int, bool mostly) and two navigation properties/links to other entities.
Breeze is configured to use the v3/'original' odata adapter:
breeze.config.initializeAdapterInstance('dataService', 'odata', true);
If I create a new entity
var manager = new breeze.EntityManager('odataEndPointHere');
manager.fetchMetadata().then(() => {
var newEvaluation = manager.createEntity('Evaluation', {Name:'Foo'});
});
then this newEvaluation will reference all primitive fields and the navigation properties (called Validation - a TPH type - and Replacements - a ~normal~ 1:1 entity relation). If I expand() that relation, I can query for existing Evaluations and will see the expected Validation value.
Grabbing an existing Validation instance and assigning it seems to work as well:
manager.fetchEntityByKey('Validation', existingIdHere).then(validation => {
newEvaluation.Validation = validation; // works, while assigning a non-entity throws
});
But if I call manager.saveChanges(); the server reports that there's no (mandatory) Validation link. Looking at the POST to the $batch endpoint I see that breeze really only posts a subset of the Evaluation type, only posts the primitive fields and none of the navigation properties. This happens for both existing (fetched and updated) and new (createEntity) objects.
Now, I understand that I've yet to create a small test case - given that this is a service that I cannot directly control I'm still trying to figure out how I'm going to provide a reduced recipe for reproduction.
That said:
breeze can query all my entities, just fine. Expanding the navigation properties works flawlessly
breeze completely ignores the very same properties during saveChanges() for me
(unrelated?) breeze offers no way for me to set the FK ID only (http://breeze.github.io/doc-js/navigation-properties.html, "Setting the Foreign Key directly") although it does list the navigation properties in manager.metadataStore.getEntityType("Evaluation").navigationProperties
Edit:
The $metadata result contain this for the entities in question:
<EntityType>
<!-- snip the rest --->
<NavigationProperty Name="Evaluations" Relationship="MyNamespace.Entities.FK_Evaluation_Validation" ToRole="Evaluation" FromRole="Validation" />
</EntityType>
and later:
<AssociationSet Name="FK_Evaluation_Validation" Association="MyNamespace.Entities.FK_Evaluation_Validation">
<End Role="Validation" EntitySet="Validations" />
<End Role="Evaluation" EntitySet="Evaluations" />
</AssociationSet>
I'm including dynamic content to a view using a custom Thymeleaf attribute processor that simply adds additional nodes while processing the attribute itself.
The code I use is very similar to the one below:
final Template template = arguments.getTemplateRepository().getTemplate(
new TemplateProcessingParameters(arguments.getConfiguration(), "name-of-a-view", arguments.getContext()));
final List<Node> children = template.getDocument().getChildren();
// Add to the tree.
for (final Node node : children) {
element.addChild(node);
}
This works fine, but breaks when the included nodes contains forms that use th:object and th:field.
I put the model I need inside the node variable map and in fact th:object does find and retrieves the object, but th:field does not seems to care and breaks with a
Neither BindingResult nor plain target object for bean name 'model' available as request attribute
From my understanding (step-by-step debugging), it seems to me that th:field only search for the model in the request context.
Am I missing something here?
Thank you in advance.
No, you're spot on. I'm still not sure why the binding is different for th:field than other th: attributes, but it definitely works differently. Essentially, you can't use th:field unless your th:object is on the model. The workaround is to stop using th:field and just specify your input attributes manually, like:
<form action="#" th:action="#{/process}" th:object="${objectFromList}" method="post">
<input type="text" id="fieldName" name="fieldName" th:value="*{fieldName}" />
</form>
I realize this post is old. Hopefully, this will help someone who is running into this quirk.
In struts2 we use
<action name="anAction">
<result name="success">xx.jsp</result>
</action>
to define action, and use s:url to generate a link to the action
<s:url action="anAction"></s:url>
The above s:url will output "/anAction.do".
I wonder if it's possible to let s:url generate a default URL parameter (i.e. /anAction.do?p=xxx for all links), without modifying the existing s:url tags (there are many and they are scattered). The goal is to let the parameter appear in the link for SEO purpose.
Available options can be: changing any action config, changing any struts config, even rewrite the s:url generation class.
Edit: I found that adding this to struts.xml
<constant name="struts.url.includeParams" value="get" />
partially solves my problem (as long as the initial page has ?p=xxx, all subsequent links will have it). The short-comings are obvious: the parameter will not follow a redirect action. I am still searching for more sophisticated solution.
I did figure out how this can be done. The steps are:
1) create a class which implements org.apache.struts2.components.UrlRenderer
2) register that class with struts object factory and it will be injected as necessary
Details? Ok.
1) For example, a subclass of ServletUrlRender might look like this:
package com.example;
import java.util.Map;
import org.apache.struts2.components.ServletUrlRenderer;
import org.apache.struts2.components.UrlProvider;
public class ParameterInjectingUrlRenderer extends ServletUrlRenderer {
#Override
protected void mergeRequestParameters(String value, Map<String, Object> parameters, Map<String, Object> contextParameters) {
super.mergeRequestParameters(value, parameters, contextParameters);
parameters.put("myParameter", "secretvalue");
}
}
2) In struts.xml, set this class as the renderer implementation, with a line like this:
<constant name="struts.urlRenderer" value="parameterInjectingUrlRenderer" />
(In this example I'm using a Spring object factory, and value references a spring bean id. If you are not, I believe you put the fully-qualified class name).
That's it!
Global Search and replace (All IDE's should have this feature)
<s:url action="anAction"></s:url>
With
<s:url action="anAction"><s:param name="p" value="'xxx'"/></s:url>
Now every "anAction" will have a parameter p with value xxx.
It generally a good idea to specify the namespace.
<s:url namespace="/" action="anAction"><s:param name="p" value="'xxx'"/></s:url>
I'm coming from a Spring MVC background on a new Grails app. I have an object that contains a list of dependent objects. On the create and edit screen, I want to edit that object and its list of objects at the same time. In Spring MVC, you could use special names to bind the form fields to items in a list. Example:
Entity { String name, List items }
<form:input name="entity.items[0].value" value="${entity.items[0].value}"/>
I've tried similar variations in my GSP create and edit forms, but no luck.
I haven't used this with tag (is it a Java taglib?), but what you are doing is along the right path. I don't think you need the entity in there, the name should be just "items[0].value"
Here is some code I have that does what you need (using HTML input tag):
<input type="text" name="subItems[0].date"/>