How to 'package' request parms into one object - spring-mvc

If you have a controller method which has a whole bunch of parameters such as:
getSomething (String a, int b, Timestamp c, etc...)
what is the best way to replace those with an object, so you do not have to then instantiate a new object and set all those from the parameters, like so:
SomeObject o = new SomeObject();
o.setA(a);
o.setB(b);
o.setC(c);
etc..
// use o on other method calls to prepare a response
I have tried #ModelAttribute like so:
getSomething (#modelAttribute SomeObject o)
but it does not seem to work well unless you only use simple types for properties such as strings and ints. A Timestamp property for example causes it to fail with a "Bad Request"
#RequestBody could work, but with some pretty significant changes required to your method call which ends up that you can no longer simply call that method by the browser anymore to test it, which makes development much more annoying.
Is there no way to tell Spring to accept a bunch of parameters in a regular http GET request and use them to instantiate an object for you with the ability to work with all property data types?

You probably need to write a type converter for the Timestamp class, and register it with Spring MVC ConversionService.
See http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html
Why can't you use a Date or DateTime (Joda Time) class?
Make sure you use the #Timestamp annotation if using JPA

Related

Cannot deserialize an object using a converter?

Given a JSON string of the form {"$type":"MyType, MyAssembly","seed":0"}, why can't JsonConvert.DeserializeObject utilize the JsonConverter associated with "MyType"?
I've tried decorating the MyType class with a [JsonConverter(typeof(MyType))] attribute. Doesn't work. The custom JsonConverter's ReadJson method is never called.
I've tried adding the custom converter to the serializer's settings Converters collection and made sure the CanConvert method returns true for 'MyType' and the CanRead method returns true. Doesn't work. Neither the converter's CanConvert nor its ReadJson method is ever called.
The DeserializeObject method needs to be able to deserialize a JSON string containing an object whose type is unknown at compile time, but whose type is embedded in the JSON object via the special "$type" member. So don't suggest using DeserializeObject<T> or point out that it works for members, whose type is identified in the contract before hand.
FYI, this problem generalizes to cases where the deserialization needs to identify the object type solely from the embedded "$type" member, so for example, it also fails to resolve a converter if the JSON object is in an untyped JSON array, not just at the top-level.
Basically, an object cannot survive a round trip through the serialization/deserialization process, because although the WriteJson method will be called for the Converter when SerializeObject is called, when you subsequently pass the JSON string to DeserializeObject, it fails to call the converter's ReadJson method, and instead constructs an new instance and uses the basic member population routines.

Modifying a Biztalk message from custom code

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.

Manually doing what the ModelAttribute annotation does in Spring MVC

I have an action method on a Spring MVC controller that has an argument annotated with #ModelAttribute. However, I don't know at compile time what the type of this parameter will be - I know the abstract base type but not the derived type.
At runtime, I will be able to decide what class I am expecting and I will be able to get a new'd up instance of this class. However, I have no idea what code I should be calling to parse the request data in the same fashion that #ModelAttribute does.
I've looked around and it seems that if i can get a hold of a WebRequestDataBinder I can use that to populate my object, but for that I need a BinderFactory and this is where I kind of get lost.
Can anyone give me some pointers here - or tell me that I am looking at it the wrong way and need to do something else?
you can inject the model itself in your controllers method and access the attribute yourself.
#RequestMapping(...)
public void doStuff(ModelMap model) {
Object attr = model.get("nameOfAttribute");
// ...
}

Is it possible to insert different java.lang.Objects from a JSP <form> into a Map in Struts2?

Struts2 inserts java.lang.Strings into Maps as default, but... is there a way to override that behavior for some parameters and insert different Objects using many custom Type Converters?
For example, in a Java class we can declare a HashMap and put something like:
myHashMap.put(“name”,”myName”); //this is a String
myHashMap.put(“id”,new Integer(“101”)); //this is an Integer
myHashMap.put(“date”,java.util.Calendar.getInstance().getTime()); //this is a Date
Is it possible to assign the correct java.lang.Object directly from the <s:form> using Type Converters?
If you have something like this in your <s:form>:
<s:textfield name="myHashMap['name']"/>
<s:textfield name="myHashMap['id']"/>
<s:textfield name="myHashMap['date']"/>
Every value ends as a java.lang.String inside the HashMap, instead of having a String, an Integer an a Date...
I tried to create my own Type Converter with no luck... I guess Struts2 wants a POJO with setters and getters for each parameter, but the HashMap uses the “put(Key,Value)” method.
I have the setters and getters for “myHashMap”, but I thought Struts would somehow use it like a POJO when setting the parameters (when calling “put(Key,Value)”).
I created “MyAction-conversion.properties” file and wrote this:
date=app.converter.MyDateConverter
It didn't work... Then I tried also doing this:
myHashMap['date']=app.converter.MyDateConverter # (didn't work)
myHashMap.date=app.converter.MyDateConverter # (didn't work)
The converter isn't called at all! I do have “MyDateConverter” class and it is working fine. If I use a POJO (instead of the HashMap) and create the setters and getters inside the POJO for “name”, “id” and “date” it works great. But the thing is that I want to use something more generic, like a HashMap, in order to change the name of the parameters in the form or add more without having to create another POJO.
For the moment, it works using the HashMap if you expect to receive only Strings, but I don't know how to call a Type Converter to receive custom Objects. The converter isn't called and I end always with Strings.
struts2 can convert java.util.Date from String without coding your converter. Infact,'date' is String type ,struts can not find it by it's content but type.
Doubtful, and if you can, don't. Doing so would require the use of a raw map and casting to retrieve the values. Type safety is your friend.
But the thing is that I want to use something more generic, like a HashMap, in order to change the name of the parameters in the form or add more without having to create another POJO.
That isn't a better design. Stick with the POJO approach.

NHibernate.IFutureValue<> when serialized includes .Value

I'm building an ASP.NET (2.0, no, I can't change it) site with NHibernate, and have a custom JSON converter so I can not-serialize properties I want hidden from the client. This lets me just return the objects, and never have to worry about their serialized values - they're always secure.
Unfortunately, it appears that if I use query.FutureValue<class>(), the object that gets serialized is first the NHibernate.Impl.FutureValue<class> and not my entity, which means I get JSON that looks like this if I throw it in a dictionary and return it to the client:
{key: { Value: { /* my serialized object properties */ } }
Previously I discovered that I can't get any interfaces to work in ASP's JavaScriptConverter implementations... only regular or abstract classes. So returning typeof(IFutureValue<MyBaseClass>) as a supported type means my converter is completely ignored. I can catch MyBaseClass, because I refactored things earlier to use an abstract base instead of an interface, but not the interface.
And then I discover that the FutureValue implementation in .Impl is internal to the assembly, or some other such nonsense that only serves to make my .NET experience even more painful. So I can't use typeof(FutureValue<MyBaseClass>) to handle it all, because FutureValue exists only in my debugging sessions.
Is there a way to get the class type out of the assembly? Or a way to convince ASP that interfaces do in fact have uses? Or might there be some superclass I can access that would let me get around the whole issue?
Help! I like my Futures, it lets me batch a whole heck-ton of calls at once!
(if something isn't clear, or you want more code, by all means, ask! I can post quite a bit.)
If I'm understanding you correctly, it seems you are mixing things a together a little bit.
It sounds like you're trying to serialize an instance of query.FutureValue<class>(), which unsurprisingly gives you just that: a JSON object where the Value fields has JSON representing your entity.
To me it sounds like you really want to just serialize query.FutureValue<class>().Value.
Using NHibernate futures like this gives you little benefit though, so you're probably after something like:
var future1 = query1.FutureValue<SomeEntity>();
var future2 = query2.FutureValue<AnotherEntity>();
var json1 = serializer.Serialize(future1.Value); //<BAM! Multi-query gets fired!
var json2 = serializer.Serialize(future2.Value);
Does that make sense?

Resources