I followed the demo project here https://codeeffects.com/Doc/Business-Rule-Flex-Source for a sample of how the Flex properties work. My rules are evaluated correctly, but the editor does not show the fields.
I have looked at all of the properties of the FlexPropertyInfo object and confirmed that they set as I would expect. What else should I try in order to troubleshoot this?
Make sure that your Flex type inherits from Type and implements the minimum required properties and methods, and GetProperties in particular, e.g.:
public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
{
List<FlexPropertyInfo> properties = new List<FlexPropertyInfo>();
properties.Add(new FlexPropertyInfo("Id", typeof(int), typeName));
properties.Add(new FlexPropertyInfo("Name", typeof(string), typeName));
return properties.ToArray();
}
Make sure that you pass a new instance of your Flex type and not the type itself.
RuleEditor editor = new RuleEditor("divRuleEditor")
{
Mode = Common.RuleType.Execution,
SourceType = new MyFlexType() //and not typeof(MyFlexType)
}
The Editor itself knows nothing about Flex. As far as it is concerned it is another type and it is using reflection to pull the list of all members. Which is why it is important to pass an instance of your type. Otherwise you will get reflection on the Type class instead. Same goes for properties and other Flex objects.
Related
In Json.NET, how do I make ALL properties required upon deserialization? I know that I can do this with attributes on the messages, but I don't want to do that. Mainly because it would require my message library to take on an external dependency.
I tried the MissingMemberHandling.Error setting, but it does the opposite of what I want. I'm okay with the JSON having extra properties. I want it to fail when any target object properties are missing in the JSON.
I'm actually deserializing to F# records, and the properties can't ordinarily be null anyway. (They can't be assigned null by normal means in code.) But Json.NET happily defaults properties to null under the covers when data is missing.
F# version of accepted answer
Resolver
open System
open Newtonsoft.Json
open Newtonsoft.Json.Serialization
type RequireAllPropertiesContractResolver() =
inherit DefaultContractResolver()
override me.CreateObjectContract(objectType:Type) =
let contract = base.CreateObjectContract(objectType)
contract.ItemRequired <- new Nullable<Required>(Required.Always)
contract
In the settings
let settings = new JsonSerializerSettings() // default settings
...
settings.ContractResolver <- new RequireAllPropertiesContractResolver()
If your model has properties that your JSON may omit, and you want that to be an error, add the attribute [JsonObject(ItemRequired=Required.Always)] to your classes:
Type: Required
A value indicating whether the object's properties are required.
Possible values for Required are:
Default: The property is not required. The default state.
AllowNull: The property must be defined in JSON but can be a null value.
Always: The property must be defined in JSON and cannot be a null value.
DisallowNull: The property is not required but it cannot be a null value [if present]. (Json.NET 8.0.1 and later.)
The setting is inherited so can be added to a generic base class.
Update
To do it globally for all objects, subclass the DefaultContractResolver and add the ItemRequired flag to all object contracts:
public class RequireObjectPropertiesContractResolver : DefaultContractResolver
{
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
var contract = base.CreateObjectContract(objectType);
contract.ItemRequired = Required.Always;
return contract;
}
}
And then later, in settings:
var settings = new JsonSerializerSettings { ContractResolver = new RequireObjectPropertiesContractResolver() };
Notes:
If you don't want to require JSON properties when your f# member is optional see this answer to this question and also the question Json.NET make property required based on property type.
This contract resolver applies a default setting of Required.Always to all object properties, but will not override JsonProperty.AttributeRequired when applied directly. If you need that, see e.g. How to override the "Required.Always" in newtonsoft json.
As stated in the question, the setting MissingMemberHandling = MissingMemberHandling.Error solves a complimentary problem: if your JSON may have properties that your model omits, and you want that to be an error, use MissingMemberHandling.Error. See: MissingMemberHandling setting.
You may want to cache the contract resolver for best performance.
I know I am late on party here, but... Accepted answer forces all properties to be available, which could be not so good for case when your record contains Option types combining with NullValueHandling.Ignore parameter on JsonSerializerSettings. In that case you would require option type to be present, which is too limiting. We found this solution works for us:
type RequireAllPropertiesContractResolver() =
inherit CamelCasePropertyNamesContractResolver()
override __.CreateProperty(memb, serialization) =
let prop = base.CreateProperty(memb, serialization)
let isRequired = not (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() = typedefof<option<_>>)
if isRequired then prop.Required <- Required.Always
prop
I hope it helps someone.
The Grails 2.5.4 docs say that it's possible to exclude properties from rendering for an entire group of domain classes.
There are some default configured renderers and the ability to register or override renderers for a given domain class or even for a collection of domain classes.
However there's no example given in the docs for how to do this. Does anyone know how to exclude properties for all of my domain classes? Specifically I'm trying to get rid of the class and enumType fields that Grails automatically adds to the response body.
There doesn't seem to be any good way to do this. What I discovered is that if you register an exclusion for a super class, all subclasses also "inherit" that exclusion. So to get rid of four properties for all Groovy objects (which cover all domain classes), I added the following bean to resources.groovy.
groovyObjectJsonRenderer(JsonRenderer, GroovyObject) {
excludes = ['class', 'declaringClass', 'errors', 'version']
}
I don't know if you are talking about this, but you can ignore some properties when you render as JSON, overriding the Marshaller here is the code:
static {
grails.converters.JSON.registerObjectMarshaller(NAMEOFYOURCLASS) {
return it.properties.findAll {k,v -> k != 'class' && k!='declaringClass'}
}
}
or if you want to create your custom render you can do something like this
static {
grails.converters.JSON.registerObjectMarshaller(NAMEOFYOURCLASS) {
def lista = [:]
lista['id'] = it.id
lista['name'] = it.name
lista['dateCreated'] = it.date?.format("dd/MM/yyyy HH:mm")
return lista
}
}
You can put it where you think its better i actually prefer to put it in the class i'm overriding, because letter i can find it or if some one else it's looking the code, he/she can find it easy.
In Json.NET, how do I make ALL properties required upon deserialization? I know that I can do this with attributes on the messages, but I don't want to do that. Mainly because it would require my message library to take on an external dependency.
I tried the MissingMemberHandling.Error setting, but it does the opposite of what I want. I'm okay with the JSON having extra properties. I want it to fail when any target object properties are missing in the JSON.
I'm actually deserializing to F# records, and the properties can't ordinarily be null anyway. (They can't be assigned null by normal means in code.) But Json.NET happily defaults properties to null under the covers when data is missing.
F# version of accepted answer
Resolver
open System
open Newtonsoft.Json
open Newtonsoft.Json.Serialization
type RequireAllPropertiesContractResolver() =
inherit DefaultContractResolver()
override me.CreateObjectContract(objectType:Type) =
let contract = base.CreateObjectContract(objectType)
contract.ItemRequired <- new Nullable<Required>(Required.Always)
contract
In the settings
let settings = new JsonSerializerSettings() // default settings
...
settings.ContractResolver <- new RequireAllPropertiesContractResolver()
If your model has properties that your JSON may omit, and you want that to be an error, add the attribute [JsonObject(ItemRequired=Required.Always)] to your classes:
Type: Required
A value indicating whether the object's properties are required.
Possible values for Required are:
Default: The property is not required. The default state.
AllowNull: The property must be defined in JSON but can be a null value.
Always: The property must be defined in JSON and cannot be a null value.
DisallowNull: The property is not required but it cannot be a null value [if present]. (Json.NET 8.0.1 and later.)
The setting is inherited so can be added to a generic base class.
Update
To do it globally for all objects, subclass the DefaultContractResolver and add the ItemRequired flag to all object contracts:
public class RequireObjectPropertiesContractResolver : DefaultContractResolver
{
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
var contract = base.CreateObjectContract(objectType);
contract.ItemRequired = Required.Always;
return contract;
}
}
And then later, in settings:
var settings = new JsonSerializerSettings { ContractResolver = new RequireObjectPropertiesContractResolver() };
Notes:
If you don't want to require JSON properties when your f# member is optional see this answer to this question and also the question Json.NET make property required based on property type.
This contract resolver applies a default setting of Required.Always to all object properties, but will not override JsonProperty.AttributeRequired when applied directly. If you need that, see e.g. How to override the "Required.Always" in newtonsoft json.
As stated in the question, the setting MissingMemberHandling = MissingMemberHandling.Error solves a complimentary problem: if your JSON may have properties that your model omits, and you want that to be an error, use MissingMemberHandling.Error. See: MissingMemberHandling setting.
You may want to cache the contract resolver for best performance.
I know I am late on party here, but... Accepted answer forces all properties to be available, which could be not so good for case when your record contains Option types combining with NullValueHandling.Ignore parameter on JsonSerializerSettings. In that case you would require option type to be present, which is too limiting. We found this solution works for us:
type RequireAllPropertiesContractResolver() =
inherit CamelCasePropertyNamesContractResolver()
override __.CreateProperty(memb, serialization) =
let prop = base.CreateProperty(memb, serialization)
let isRequired = not (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() = typedefof<option<_>>)
if isRequired then prop.Required <- Required.Always
prop
I hope it helps someone.
Using this abstract class:
#JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
#JsonSubTypes({ #JsonSubTypes.Type(value = PostingTaskInstanceDto.class, name = "TI") })
public abstract class BasePostingDto {}
and this inherited class:
public class PostingTaskInstanceDto extends BasePostingDto {}
I get correct serialization for a single object. This works, using Spring-MVC:
#RequestMapping("/{id}")
#ResponseBody
public BasePostingDto findById(#PathVariable("id") Long id) {
return createDto(postingService.findById(id));
}
But if I retrieve a List of BasePostingDto from the remote controller, the type property is missing:
#RequestMapping("/by-user/all")
#ResponseBody
public List<BasePostingDto> findByUser() {
return createDtoList(postingService.findByUser(AuthUtils.getUser()));
}
Why is this and how can I force the type property?
Update: the type property is also included if I change List<BasePostingDto> to BasePostingDto[], however I would prefer to go with the List.
It sounds like the framework you are using (and which uses Jackson under the hood) is not passing full generics-aware type information.
I don't know how that can be fixed (it is problem with integration by framework, and not something Jackson can address), but the usual work around is for you to use sub-class of List:
public class PostingDtoList extends List<BasePostingDto> { }
and use that in signature, instead of generic type. This solves the issue because then the generic type signature is retained (since it is stored in super type declaration, and accessible via type-erased PostingDtoList class!).
In generally I think it is best to avoid using generic List and Map types as root type (and instead use POJO); partly because of problems issued (there are bigger problems when using XML for example). But it can be made to work if need be.
I have a swing app with a text box bound to a property on my model (this is a READ_WRITE AutoBinding). The model also has an isDirty property that I want to bind to a button's enabled property.
How do I properly notify the binding when I change the state of isDirty.
Here is my binding code:
BeanProperty<PaChannelConfig, Boolean> paChannelConfigBeanProperty_1 =
BeanProperty.create("dirty");
BeanProperty<JButton, Boolean> jButtonBeanProperty =
BeanProperty.create("enabled");
AutoBinding<PaChannelConfig, Boolean, JButton, Boolean> autoBinding_2 =
Bindings.createAutoBinding(
UpdateStrategy.READ,
model,
paChannelConfigBeanProperty_1,
btnApply, jButtonBeanProperty);
autoBinding_2.bind();
What is the proper way to add this notification?
Basically, the model should have the methods
addPropertyChangeListener(PropertyChangeListener)
removePropertyChangeListener(PropertyChangeListener)
firePropertyChange(PropertyChangeEvent)
look at the class PropertyChangeSupport, that class have implementations of the methods above.
In the model, the method setDirty(boolean) should be implemented like this:
public void setDirty(boolean dirty) {
boolean old = this.dirty;
this.dirty = dirty;
firePropertyChange(new PropertyChangeEvent("dirty", old, dirty));
}
hope that helps
You can use PropertyChangeSupport to easily implement support for property change notification. The documentation at the provided link has an example of how to set it up and use it.