We are using https://github.com/Azure/amqpnetlite from the Azure team.
The description says we have to use the AmqpContract and AmqpMember attribute classes over the message bus like ActiveMQ.
We also have a lot of classes and we want to migrate to this Amqp library, but is it possible to use the serializer without those attributes and to use our POCO classes directly?
Another workaround could(?) be to serialize or classes into a json and use a wrapper class to send our payload:
[AmqpContract]
public class OurMessage
{
[AmqpMember]
public string JsonPayload {get;set;}
}
or should we avoid this workaround?
The POCO classes as you mentioned are not supported right now. You will need to pick another serializer. Once you have the JSON string or a byte array, you do not need to define a wrapper class. Just directly create an AMQP message with the payload and get it back from the message body on the receiver side.
// sender
var msg = new Message(jsonPayload);
sender.Send(msg);
// receiver
var msg2 = receiver.Receive();
var jsonPayload = msg2.GetBody<string>();
Same thing can be done for byte array.
The AMQP serializer is designed to be simple and everything has to be explicitly annotated. For most cases this is possible and it helps to avoid double encoding and enable easier inter-op with other AMQP clients.
Related
For example, from Scout Form execStore() method, right before executing any server services, i like to get the HttpSession and eventually get custom data from its attributes store.
As mentioned in the comments, Eclipse Scout separates the UI Layer (the HTML rendering - or the Swing client in older versions) from the client model. And while the UI Layer knows about the HttpSession, the client model, in which your form lives, does not.
You can however put the relevant attributes on the ServerSession (backend) and synchronize them to the ClientSession (model) or vice versa - depending on where your attributes come from.
This sketch should get you started:
In your Client/ServerSession class (extends AbstractServerSession) add a getter and setter.
If - and only if - you need to synchronize the values to the client implement the getter / setter like this (example for an Integer property):
public Integer getMyProperty() {
return getSharedContextVariable("myProperty", Integer.class);
}
public void setMyProperty(Integer newValue) {
setSharedContextVariable("myProperty", Integer.class, newValue);
}
You'll need to teach the application to transfer the data to your Client or ServerSession.
If your data comes from the backend side (e.g. from database): Your best guess is to override the default implementation of org.eclipse.scout.rt.server.context.HttpServerRunContextProducer.
Create a subclass of this class in your .server-part, and add the #Replace annotation. Your best place to implement it is likely in the method public IServerSession getOrCreateScoutSession(HttpServletRequest req, ServerRunContext serverRunContextForSessionStart, String scoutSessionId)
If your data comes from the UI side (e.g. passed by SAML):
This is more complicated and I have only hints where to start looking: org.eclipse.scout.rt.ui.html.UiSession.createAndStartClientSession(Locale, UserAgent, Map<String, String>) on how the ClientSession is created and if you can access your data at this location.
Disclaimer: I am a complete biztalk newbie.
I need to be able to read and potentially edit 4 nodes in a biztalk message; preferably this needs to be done from a c# helper class as I am making a service call and also have unit tests written for this.
I already have this class wired up and it works with the XLANGMessage class, the problem I am running into is at this point in the orchestration the message is a Schema based type and doesn't seem to have any way for me to modify it.
I've done some reading and found a few ideas but have not been able to confirm if any of these can work from custom code.
1 write a map to transform the incoming message to the desired type
or
2 write something like this in your helper component to transform the message
public XmlDocument TransformMessage(XLANGMessage message)
Then pass the result document to a biztalk message in a message assignment shape.
responseMessage = xmlDocument;
You may get better performance if you pass streams instead of messages around.
You can pass messages into and out of C# helper classes easily. The simplest way is just to treat input parameters and return values as of type System.Xml.XmlDocument. The XLANG/s engine will safely cast back and forth from the XLANGMessage type to XmlDocument.
As you are essentially creating a "new" instance of the message (messages are immutable in BizTalk), the call to your helper class needs to be performed in a Message Assignment shape, with the outer Construct shape constructing the copy of your original message.
public static XmlDocument UpdateMyMessage(XmlDocument sourceMessage)
{
/* Do stuff to your Message here */
return sourceMessage;
}
A best-practice to consider is to declare all your C# helper methods as Static. This will avoid any issues with de/serialisation of your helper class during dehydration.
Are BizTalk messages immutable?
Generally speaking they are however, by creating a “corrective” orchestration and using a pass by reference option on the incoming message parameter, an existing message can be modified.
I have a WCF Rest Service. I would like to use it from Android device. To do this I have chosen gson library. Everything seemed to work fine until I wanted to return from my service Object Containing Map. Gson serializes it (and as I am assuming also tries to deserialize from it) as something like:
{"org.Mob.ComplexObject#3dac2f9c":"TAX1","org.Mob.ComplexObject#7369ca65":"TAX2"}
But the json sent by my service looks like:
{"Key":
{"DefaultValue":"True",
"Description":null,
"DisplayName":"Custom Boolean",
"FieldType":0,
"Id":6,
"IsReadOnly":false,
"IsRequired":false,
"MaxLength":null,
"Name":"BoolVal",
"ParamType":0},
"Value":"True"},
{"Key":
{"DefaultValue":"",
"Description":null,
"DisplayName":"Custom Text",
"FieldType":4,
"Id":7,
"IsReadOnly":false,
"IsRequired":true,
"MaxLength":16,
"Name":"TextVal",
"ParamType":0},
"Value":"sda"}
}
Gson does not have a built-in feature to serialize a Java map into JSON formatted as desired. (The feature to handle complex map keys does not address this.) Custom serialization/deserialization processing is necessary.
The other way to do it could be adding you own implementation of Map / Dictionary which extends ArrayList, and in fact is a List of KVPair, where KVPair looks like:
class KVPair<K,V>{
K Key;
V Value;
}
I don't know if it's elegant, but it worked in my case.
Thought Id ask here before jumping into a problem on the Blackberry Playbook (Adobe Flex)
I have a search form and a SearchCriteria class representing the search form's input, for example:
public class SearchCriteria
{
private var firstname:String;
private var surname:String;
public function SearchCriteria()
{}
public function getFirst():String{
return firstname;
}
...
As the person fills out the form, I would like to cache a copy in memory of the SearchCriteria so that if there is a problem, or the user turns off their tablet, I could recreate the form when they log back in.
TL;dr version: Basically, what is the best way to Serialize and Deserialize objects in Actionscript 3? (particularly on the Blackberry Playbook)
Thanks
Phil
If you are asking specifically about serialization and deserialization I'd recommend AMF3 format.
It is used by SharedObject mentioned by Timofei Davydik. You can also serialize objects with ByteArray.writeObject() and then save the ByteArray to a file.
Note that if you want to use strongly typed object (recommended) you should annotate your model classes with [RemoteClass] metadata. If you don't want some properties to be serialized use [Transient] metadata.
You could serialize them to JSON format using the as3corelib library.
And then use SharedObject or SQLite (works well in Playbook).
Read about SharedObject class.
What options are there for serialization when returning instances of custom classes from a WebService?
We have some classes with a number of child collection class properties as well as other properties that may or may not be set depending on usage. These objects are returned from an ASP.NET .asmx WebService decorated with the ScriptService attribute, so are serialized via JSON serialization when returned by the various WebMethods.
The problem is that the out of the box serialization returns all public properties, regardless of whether or not they are used, as well as returning class name and other information in a more verbose manner than would be desired if you wanted to limit the amount of traffic.
Currently, for the classes being returned we have added custom javascript converters that handle the JSON serializtion, and added them to the web.config as below:
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization>
<converters>
<add name="CustomClassConverter" type="Namespace.CustomClassConverter" />
</converters>
</jsonSerialization>
</webServices>
</scripting>
</system.web.extensions>
But this requires a custom converter for each class. Is there any other way to change the out of the box JSON serialization, either through extending the service, creating a custom serializer or the like?
Follow Up
#marxidad:
We are using the DataContractJsonSerializer class in other applications, however I have been unable to figure out how to apply it to these services. Here's an example of how the services are set-up:
[ScriptService]
public class MyService : System.Web.Services.WebService
{
[WebMethod]
public CustomClass GetCustomClassMethod
{
return new customClass();
}
}
The WebMethods are called by javascript and return data serialized in JSON. The only method we have been able to change the serialization is to use the javascript converters as referenced above?
Is there a way to tell the WebService to use a custom DataContractJsonSerializer? Whether it be by web.config configuration, decorating the service with attributes, etc.?
Update
Well, we couldn't find any way to switch the out of the box JavaScriptSerializer except for creating individual JavaScriptConverters as above.
What we did on that end to prevent having to create a separate converter was create a generic JavaScriptConverter. We added an empty interface to the classes we wanted handled and the SupportedTypes which is called on web-service start-up uses reflection to find any types that implement the interface kind of like this:
public override IEnumerable<Type> SupportedTypes
{
get
{
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
AssemblyBuilder dynamicAssemblyCheck = assembly as AssemblyBuilder;
if (dynamicAssemblyCheck == null)
{
foreach (Type type in assembly.GetExportedTypes())
{
if (typeof(ICustomClass).IsAssignableFrom(type))
{
yield return type;
}
}
}
}
}
}
The actual implementation is a bit different so that the type are cached, and we will likely refactor it to use custom attributes rather than an empty interface.
However with this, we ran into a slightly different problem when dealing with custom collections. These typically just extend a generic list, but the custom classes are used instead of the List<> itself because there is generally custom logic, sorting etc. in the collection classes.
The problem is that the Serialize method for a JavaScriptConverter returns a dictionary which is serialized into JSON as name value pairs with the associated type, whereas a list is returned as an array. So the collection classes could not be easily serialized using the converter. The solution for this was to just not include those types in the converter's SupportedTypes and they serialize perfectly as lists.
So, serialization works, but when you try to pass these objects the other way as a parameter for a web service call, the deserialization breaks, because they can't be the input is treated as a list of string/object dictionaries, which can't be converted to a list of whatever custom class the collection contains. The only way we could find to deal with this is to create a generic class that is a list of string/object dictionaries which then converts the list to the appropriate custom collection class, and then changing any web service parameters to use the generic class instead.
I'm sure there are tons of issues and violations of "best practices" here, but it gets the job done for us without creating a ton of custom converter classes.
If you don't use code-generated classes, you can decorate your properties with the ScriptIgnoreAttribute to tell the serializer to ignore certain properties. Xml serialization has a similar attribute.
Of course, you cannot use this approach if you want to return some properties of a class on one service method call and different properties of the same class on a different service method call. If you want to do that, return an anonymous type in the service method.
[WebMethod]
[ScriptMethod]
public object GimmieData()
{
var dalEntity = dal.GimmieEntity(); //However yours works...
return new
{
id = dalEntity.Id,
description = dalEntity.Desc
};
}
The serializer could care less about the type of the object you send to it, since it just turns it into text anyway.
I also believe that you could implement ISerializable on your data entity (as a partial class if you have code-gen'd data entities) to gain fine-grained control over the serialization process, but I haven't tried it.
I know this thread has been quiet for a while, but I thought I'd offer that if you override the SupportedTypes property of JavaScriptConverter in you custom converter, you can add the types that should use the converter. This could go into a config file if necessary. That way you wouldn't need a custom converter for each class.
I tried to create a generic converter but couldn't figure out how to identify it in the web.config. Would love to find out if anyone else has managed it.
I got the idea when trying to solve the above issue and stumbled on Nick Berardi's "Creating a more accurate JSON .NET Serializer" (google it).
Worked for me:)
Thanks to all.
If you're using .NET 3.x (or can), a WCF service is going to be your best bet.
You can selectively control which properties are serialized to the client with the [DataMember] attribute. WCF also allows more fine-grained control over the JSON serialization and deserialization, if you desire it.
This is a good example to get started: http://blogs.msdn.com/kaevans/archive/2007/09/04/using-wcf-json-linq-and-ajax-passing-complex-types-to-wcf-services-with-json-encoding.aspx
You can use the System.Runtime.Serialization.Json.DataContractJsonSerializer class in the System.ServiceModel.Web.dll assembly.
Don't quote me on this working for certain, but I believe this is what you are looking for.
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public XmlDocument GetXmlDocument()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(_xmlString);
return xmlDoc;
}