Why do i need to set IsRequired if it comes from class? - wcf

I'm having trouble to understand the situation which Is :
The Host has a service which has operationMethods
for example Calc (Myclass a)
MyClass contains 2 properties ( prop1 , prop2)
Now , the clients also whould know about MyClass via proxy and should know also contract by reference.
So when the client creates new instance of MyClass (to send it)- how can one prop can be missing ???
when he instancing new MyClass - both prop are initialized (null or what ever). so why do i need the isRequired ?

Theres no guarantee as to what language or how they are formulating their soap request, so the way they are generating it may not use a generated class that contains the property. Is required requires that is present in the message
Interaction with IsRequired
As discussed in Data Contract Versioning, the DataMemberAttribute attribute has an IsRequired property (the default is false). The property indicates whether a given data member must be present in the serialized data when it is being deserialized. If IsRequired is set to true, (which indicates that a value must be present) and EmitDefaultValue is set to false (indicating that the value must not be present if it is set to its default value), default values for this data member cannot be serialized because the results would be contradictory. If such a data member is set to its default value (usually null or zero) and a serialization is attempted, a SerializationException is thrown.

Related

Combine JsonDeserialize#contentAs with JsonDeserialize#contentConverter or JsonDeserialize#contentUsing for custom deserialization

In JsonDeserialize annotation documentation the contentAs field is supposed to define the "Concrete type to deserialize content".
I tried to use this in combination, with either a Converter (via contentConverter field of the same annotation) or a JsonDeserializer (via contentUsing field of the same annotation), by extending either StdConverter or StdDeserializer, respectively, in an attempt to create an agnostic custom deserializer.
I cannot find a way to access the JsonDeserialize#contentAs information inside any of these two classes.
I am aware that the classes I extend from have a type parameter, I just put an Object class there. Documentation states
contentAs Concrete type to deserialize content (elements of a Collection/array, values of Maps) values as, instead of type otherwise declared. Must be a subtype of declared type; otherwise an exception may be thrown by deserializer.
Apparently I am applying the #JsonDeserializer annotation on a Collection of some persistable Class. I want to deserialize each such object, solely by knowing its id. Well, if I could only get that very type I defined in the #JsonDeserializer#contentAs field...
Can anyone tell me if this is possible anyhow?
I managed to implement the agnostic deserializer withou the use of #JsonDeserializer#contentAs after all.
After reading the javadocs of com.fasterxml.jackson.databind.JsonDeserializer I concluded that my custom deserializer should implement the com.fasterxml.jackson.databind.deser.ContextualDeserializer interface.
Inside the implementation of ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property)
I could finally get access to the class type of the content of the collection, which I applied the #JsonDeserialize annotation on,
by calling:
ctxt.getContextualType().getRawClass()
NOTE that the same call inside the implementation of com.fasterxml.jackson.databind.JsonDeserializer#deserialize(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.databind.DeserializationContext) returned null, hence the need of the aforementioned interface.
All I had to do then is store the returned class in a member field (of type Class< ? >) of the custom deserializer and use it in the execution of JsonDeserializer#deserialize()
The only thing that remains to check is whether an instance of this custom deserializer is shared between threads. I only did some minor checks; I used the same implementation for two different collections of different types. I observed that ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property) was called once (among multiple deserialization invokations), for each distinct type that was going to be deserialized. After checking during debugging, it seems that the same deserializer object is used for the same type. In my case, since what I store in the member field is this type itself, I don't mind if the same deserializer is used for the same java type to be deserialized because they should contain the same value. So we 're clear on this aspect as well.
EDIT: It appears all I have to do is update the com.fasterxml.jackson.databind.deser.std.StdDeserializer#_valueClass value to the now known class. Since it is final and since the ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property) returns a JsonSerializer object, which is actually used,
instead of returning "this" serializer I can create a new one, passing the discovered class in the constructor, which actually sets the StdDeserializer#_valueClass to the class I actually want, and I'm all set!
Finally, NOTE that I didn't have to use the #JsonDeserializer#contentAs annotationfield as I get the value from the ctxt.getContextualType().getRawClass() statement inside ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property) implementation

Setting an entity's ID manually

I'm facing a little issue that I cannot understand here.
Using this chunk of code:
IEntity myEntity = controller.entityFactory.createEntityInstance(MyEntity.class)
myEntity.straightSetProperty(IEntity.ID, "anId")
myEntity.setReferenceProperty(someReference)
I get an "UOW bad usage" error
BAD SESSION USAGE You are modifying an entity ()[MyEntity] that has not been previously merged in the session.
You should 1st merge your entities in the session by using the backendController.merge(...) method.
The property being modified is [referenceProperty].
But when switching the lines it's okay
IEntity myEntity = controller.entityFactory.createEntityInstance(MyEntity.class)
myEntity.setReferenceProperty(someReference)
myEntity.straightSetProperty(IEntity.ID, "anId")
Any idea why i'm facing this issue ?
Jspresso computes the hashcode of an entity based on its id. this hashcode is indirectly used by Jspresso internally to perform some controls and other operations by using it in Hash[Map|Set].
That's why it's mandatory that :
The id is assigned as soon as the entity instance is created and before any setter or operation is performed on the entity.
The id does not change during the lifetime of the entity.
When you call :
IEntity myEntity = entityFactory.createEntityInstance(MyEntity.class)
a generated id is assigned to the entity.
In scenario 1, you first change the id (which breaks the hashcode), and call a setter. Jspresso thinks this entity has not been correctly registered because it cannot retrieve its id from the internal, hashcode based, storage.
In scenario 2, same violation but you call the setter before changing the id. But I suppose that if you call another setter afterwards, it will fail the same way.
The solution is to use the other signature of the entityFactory create method that allows to pass an id as parameter, e.g.
IEntity myEntity = entityFactory.createEntityInstance(MyEntity.class, "anId")
myEntity.setReferenceProperty(someReference)
which will immediately assign your id to the entity and perform all necessary operations afterwards.

How to get the translation of an enumeration field?

In an entity, I have an enumeration field which is translated in english and french.
In the same entity, I have a computed field that I am using as a toString, so I would like to build the computed field with the enumeration value translated in english or french, depending on the user's locale.
My question : in the getter of my computed field written in the extension of the entity, how could I get the user's locale and translate the enumeration value ?
You have to make your extension aware of its execution context. There are several interfaces that you can implement in your extensions so that they get injected with elements of their running context.
org.jspresso.framework.model.component.IComponentFactoryAware to receive an ICompoentFactory instance
org.jspresso.framework.security.ISubjectAware to receive the instance of the logged-in Subject
org.jspresso.framework.application.backend.session.IApplicationSessionAware to receive the current instance of IApplicationSession
org.jspresso.framework.model.entity.IEntityLifecycleHandlerAware to receive an instance of IEntityLifecycleHandler
In order to fulfill your use-case, the 4th interface must be implemented. Your extension will be injected with an instance of IEntityLifecycleHandler through the following method :
void setEntityLifecycleHandler(IEntityLifecycleHandler);
Just store this instance in your extension implementation as an instance parameter and use it afterwards in your code by safely casting it as a org.jspresso.framework.application.IController.
For instance :
public String getI18nLabel() {
String translationKey = "ENUM_NAME." + getComponent().getEnumValue();
IController controller = (IController) lifecycleHandler;
return controller.getTranslation(translationKey, controller.getLocale());
}
Just remember that the pattern for the I18N resource bundle key of enumerations is ${ENUM_NAME}.${ENUM_VALUE} which is computed as the translationKey local variable in the code above.

Create a property dynamically

I have an Structure in a Class where i have a property named 'Name'. and other properties values inside the structure depends of the set of this value, is there any way to make them publics only when this first property is Set ?.
When i create an instance of the class , and access to this structure all the properties are available.
I would hook up these properties with an ICommand implementation.
For each property that depends on Name, they can use CanExecute to determine if Name is set. If so, CanExecute will return true, and the Command will be executed for the property (which can hook up to a method to do anything you want...get a value, set a value, etc.)
More information here

How to check if field exists that has isRequired set to true in WCF

I have a DataMember(isRequired:=True) that property is called FillerInd. Now how do you tell if that field is empty or does not exist? I was reading online and you have to do some Serialization and Deserialization of XML if it has the field required missing it will throw the exception MissingMethodException. I have no idea of how to implement this or if this is the best route to take. Any help to put me into correct path I would really appreciate it.
The DataMember property IsRequired tells you whether the property is required on the wire: whether it should be present in the message or not. A typical situation where this would cause exceptions is when the service updates the DataContract by adding a property with IsRequired = true, without notifying the clients. The clients will send serialized objects that don't include the property, causing an exception to be thrown.
A less typical situation but easy way to reproduce this problem using a property of a basic type is to explicitly set the EmitDefaultValue property to false. If you do this, and then try to call an operation with an object of that DataContract, an exception may be thrown. Consider this example:
// Data Contract
[DataContract]
public class Animal
{
[DataMember(IsRequired = true, EmitDefaultValue = false)]
public string Name;
}
// IService
[OperationContract]
int GetIdentifier(Animal animal);
// Client operation
int id = client.GetIdentifier(new Animal()); // Causes exception
This will cause a SerializationException (in turn causing a CommunicationException) with a message along these lines:
Member Name in type ....Animal cannot be serialized. This exception is usually caused by trying to use a null value where a null value is not allowed. The 'Name' member is set to its default value (usually null or zero). The member's EmitDefault setting is 'false', indicating that the member should not be serialized. However, the member's IsRequired setting is 'true', indicating that it must be serialized. This conflict cannot be resolved. Consider setting 'Name' to a non-default value. Alternatively, you can change the EmitDefaultValue property on the DataMemberAttribute attribute to true, or changing the IsRequired property to false.
Note that if you bypass this issue client side (e.g. by editing the reference.cs for a generated service reference so that the DataMember is not required anymore on the client side), then the service will encounter an exception when deserializing, which will cause a Fault, I believe.
Turning to your specific remarks and questions.
You don't have to do anything to tell if the field is empty: the WCF framework handles this for you. If needed I suppose you could hook into the (de)serialization to get the heads up on this issue, or even inspect the message before it's handled.
As I said, this situation will cause SerializationExceptions and CommunicationExceptions, not a MissingMethodException.
Whether you need "IsRequired" and whether it's the "best route to take" I wouldn't know. This depends on your situation, of course.