Struts2 annotation with parameter when using json plugin - struts2

Simply I want to evaluate a property of my action and use it's value within an annotation.
The following is exactly where I want to use it.
I want to define a excludeProperties parameter at run time.
Consider the following annotation which currently works on the action:
#Result(name = "success", type = "json", params = {"root", "model", "excludeProperties", "myCollection"})
There the actions model has a myCollection collection which I do not want serialized.
However I would like to create an exclusion String (a string will do for now).
If I create a getter setter for exclusion, I would expect the following annotation to work (which does not):
#Result(name = "success", type = "json", params = {"root", "model", "excludeProperties", "${exclusion}"})
Any ideas?
I have created actions similar to this answer which shows resolving a parameter within an annotation. I am using the named variable pattern matcher to extract values from the namespace... but I just can't seem to set this parameter no matter what I do.

Part of the issue was that I was working with entity objects and serializing collections was an issue. With your own custom JSON result type you can do what ever you want. Since created getter setter for jsonModel, I just constructed what I needed there. I don't need to worry about lazy initialization errors because you need to explicitly include collections with flexjson so if you just want the primitives (which I did) then flexjson is perfect.
This very simple result type using flexjson which worked for my needs:
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.util.ValueStack;
import flexjson.JSONSerializer;
import java.io.PrintWriter;
import org.apache.struts2.ServletActionContext;
public class Kjson implements Result {
#Override
public void execute(ActionInvocation invocation) throws Exception {
ServletActionContext.getResponse().setContentType("text/plain");
PrintWriter responseStream = ServletActionContext.getResponse().getWriter();
ValueStack valueStack = invocation.getStack();
Object jsonModel = valueStack.findValue("jsonModel");
//create json and put it into response stream
responseStream.println(new JSONSerializer().exclude("class").serialize(jsonModel));
}
}

Related

Map constructor does not assign String to Object in Grails

Given the following domain class:
class Dog {
Object name // changing the type to String fixes it
}
And this unit test:
import grails.test.mixin.Mock
import grails.test.mixin.TestMixin
import grails.test.mixin.support.GrailsUnitTestMixin
import spock.lang.*
/**
* See the API for {#link grails.test.mixin.support.GrailsUnitTestMixin} for usage instructions
*/
#TestMixin(GrailsUnitTestMixin)
#Mock([Dog])
class DogSpec extends Specification {
def setup() {
}
def cleanup() {
}
void "test something"() {
Dog dog = new Dog(name:"sparky")
// dog.name = "sparky" // adding this line also fixes it
expect:"fix me"
dog.name == "sparky"
}
}
Running grails test-app fails, but if you change the type of Dog.name to String, it works fine. Debugging brings me to realize that Dog.name never gets assigned and is null. If I were to set dog.name via regular assignment after constructing it as above, the test passes.
This issue does not occur in Groovy Script using the same map constructor assignment.
I want my type to be Object as it varies depending on the use case.
Any idea why this is happening? Is it a bug in Grails?
I did some debugging and I found out that when a field accepts an Object, grails framework doesn't do databinding on this property.
More specifically, the Dog#name field doesn't belongs to the whitelist of properties when It is declared as Object.
That's why this doesn't work.
If you want to debug, see the
grails.web.databinding.DataBindingUtils#getBindingIncludeList(final Object object)
If you put a breakpoint there, you will see how grails generates the whitelist of properties.
I think this makes a lot of sense since It's related to security!
See more about it here
If you wanna bind on an Object field nevertheless, this code may help you:
class Dog {
Object name
static constraints = {
name(bindable: true)
}
}

How to get subtypes using `DartType` class from the `analyzer`?

How can I get the subtypes of an element using the class DartType from the analyzer package?
For those wondering, the DartType class is a statically resolved type that is created by the analyzer package, Dart's static tooling package. The author is asking how they can get other types given a DartType - I think you mean super types, i.e. types that you inherit or implement.
(If you simply wanted to check if the DartType is a subtype of something, you could use isSubtypeOf)
We can get a hold of the Element that the DartType originates from, and then, if it is a ClassElement, simply return all of the super types, otherwise perhaps default to an empty list:
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
/// Returns all sub-types of [type].
Iterable<DartType> getSubTypes(DartType type) {
final element = type.element;
if (element is ClassElement) {
return element.allSupertypes;
}
return const [];
}
This is in analyzer version 0.29.3.

Dataflow output parameterized type to avro file

I have a pipeline that successfully outputs an Avro file as follows:
#DefaultCoder(AvroCoder.class)
class MyOutput_T_S {
T foo;
S bar;
Boolean baz;
public MyOutput_T_S() {}
}
#DefaultCoder(AvroCoder.class)
class T {
String id;
public T() {}
}
#DefaultCoder(AvroCoder.class)
class S {
String id;
public S() {}
}
...
PCollection<MyOutput_T_S> output = input.apply(myTransform);
output.apply(AvroIO.Write.to("/out").withSchema(MyOutput_T_S.class));
How can I reproduce this exact behavior except with a parameterized output MyOutput<T, S> (where T and S are both Avro code-able using reflection).
The main issue is that Avro reflection doesn't work for parameterized types. So based on these responses:
Setting Custom Coders & Handling Parameterized types
Using Avrocoder for Custom Types with Generics
1) I think I need to write a custom CoderFactory but, I am having difficulty figuring out exactly how this works (I'm having trouble finding examples). Oddly enough, a completely naive coder factory appears to let me run the pipeline and inspect proper output using DataflowAssert:
cr.RegisterCoder(MyOutput.class, new CoderFactory() {
#Override
public Coder<?> create(List<? excents Coder<?>> componentCoders) {
Schema schema = new Schema.Parser().parse("{\"type\":\"record\,"
+ "\"name\":\"MyOutput\","
+ "\"namespace\":\"mypackage"\","
+ "\"fields\":[]}"
return AvroCoder.of(MyOutput.class, schema);
}
#Override
public List<Object> getInstanceComponents(Object value) {
MyOutput<Object, Object> myOutput = (MyOutput<Object, Object>) value;
List components = new ArrayList();
return components;
}
While I can successfully assert against the output now, I expect this will not cut it for writing to a file. I haven't figured out how I'm supposed to use the provided componentCoders to generate the correct schema and if I try to just shove the schema of T or S into fields I get:
java.lang.IllegalArgumentException: Unable to get field id from class null
2) Assuming I figure out how to encode MyOutput. What do I pass to AvroIO.Write.withSchema? If I pass either MyOutput.class or the schema I get type mismatch errors.
I think there are two questions (correct me if I am wrong):
How do I enable the coder registry to provide coders for various parameterizations of MyOutput<T, S>?
How do I values of MyOutput<T, S> to a file using AvroIO.Write.
The first question is to be solved by registering a CoderFactory as in the linked question you found.
Your naive coder is probably allowing you to run the pipeline without issues because serialization is being optimized away. Certainly an Avro schema with no fields will result in those fields being dropped in a serialization+deserialization round trip.
But assuming you fill in the schema with the fields, your approach to CoderFactory#create looks right. I don't know the exact cause of the message java.lang.IllegalArgumentException: Unable to get field id from class null, but the call to AvroCoder.of(MyOutput.class, schema) should work, for an appropriately assembled schema. If there is an issue with this, more details (such as the rest of the stack track) would be helpful.
However, your override of CoderFactory#getInstanceComponents should return a list of values, one per type parameter of MyOutput. Like so:
#Override
public List<Object> getInstanceComponents(Object value) {
MyOutput<Object, Object> myOutput = (MyOutput<Object, Object>) value;
return ImmutableList.of(myOutput.foo, myOutput.bar);
}
The second question can be answered using some of the same support code as the first, but otherwise is independent. AvroIO.Write.withSchema always explicitly uses the provided schema. It does use AvroCoder under the hood, but this is actually an implementation detail. Providing a compatible schema is all that is necessary - such a schema will have to be composed for each value of T and S for which you want to output MyOutput<T, S>.

How to override Grails' default (binding) conversion of parameter values with commas to String array?

I'm using Grails 2.3.7 and have a controller method which binds the request to a command class. One of the fields in the command class is a String array, as it expects multiple params with the same name to be specified - e.g. ?foo=1&foo=2&foo=3&bar=0.
This works fine most of the time. The one case where it fails is if the param value contains a comma - e.g. ?foo=val1,val2&foo=val3,val4. In this case I'm getting an array with 4 values: ["val1","val2","val3","val4"], not the intended output of ["val1,val2","val1,val2"]. URL escaping/encoding the comma does not help and in my cases the param value is surrounded by quote characters as well (foo=%22a+string+with+commas,+etc%22).
I had a similar problem with Spring 3.x which I was able to solve: How to prevent parameter binding from interpreting commas in Spring 3.0.5?. I've attempted one of the answers by adding the following method to my controller:
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String[].class, new StringArrayPropertyEditor(null));
}
However this didn't work.
I also tried specifying a custom conversion service, based on the comment in https://jira.grails.org/browse/GRAILS-8997.
Config/spring/resources.groovy:
beans = {
conversionService (org.springframework.context.support.ConversionServiceFactoryBean) {
converters = [new CustomStringToArrayConverter()]
}
}
and
import org.springframework.core.convert.converter.Converter
import org.springframework.util.StringUtils
class CustomStringToArrayConverter implements Converter<String, String[]> {
#Override
public String[] convert(String source) {
return StringUtils.delimitedListToStringArray(source, ";");
}
}
but I couldn't get this to work either.
For now, I've come up with a work around. My Controller method has an extra line to set the troublesome field explicitly with:
commandObj.foo = params.list('foo') as String[]
I'm still open to suggestions on how to configure grails to not split on a comma...

How to check if two objects are of the same type in Actionscript?

I want to do this in Actionscript:
typeof(control1) != typeof(control2)
to test if two objects are of the same type. This would work just fine in C#, but in Actionscript it doesnt. In fact it returns 'object' for both typeof() expressions because thats the way Actionscript works.
I couldn't seem to find an alternative by looking in the debugger, or on pages that describe typeof() in Actionscript.
Is there a way to get the actual runtime type?
The best way is to use flash.utils.getQualifiedClassName(). Additionally, you can use flash.utils.describeType() to get an XML document the describes more about the class.
Actionscript 3 has an is operator which can be used to compare objects. Consider the following code:
var mySprite:Sprite = new Sprite();
var myMovie:MovieClip = new MovieClip();
trace(mySprite is Sprite);
trace(myMovie is MovieClip);
trace(mySprite is MovieClip);
trace(myMovie is Sprite);
Which will produce the following output:
true
true
false
false
This will work for built-in classes, and classes you create yourself. The actionscript 2 equivalent of the is operator is instanceof.
You'll want to use the Object.prototype.constructor.
From the documentation:
dynamic class A {}
trace(A.prototype.constructor); // [class A]
trace(A.prototype.constructor == A); // true
var myA:A = new A();
trace(myA.constructor == A); // true
(Conveniently, this is also how to check types in javascript, which is what originally led me to this in the docs)
So, to test this out before I posted here, I tried it in an app I have, in a class called Player. Since the prototype property is static, you can't call it using "this" but you can just skip the scope identifier and it works:
public function checkType():void {
trace(prototype.constructor, prototype.constructor == Player);
// shows [class Player] true
}
Is there a way to get the actual runtime type?
Yes.
var actualRuntimeType:Class = Object(yourInstance).constructor;
Some other answers already refer to .constructor, but you can't always directly access .constructor in ActionScript 3. It is only accessible on dynamic classes, which most classes are not. Attempting to use it on a regular class will cause a compile-time error under the default settings.
However, because every class inherits from Object, which is dynamic, we can look up their .constructor property just by casting an instance to Object.
Therefore if we are not interested in subclasses, we can confirm that two instances are of exactly the same class by simply evaluating this:
Object(instanceA).constructor === Object(instanceB).constructor;
I learned of this from the post "Get the class used to create an object instance in AS3" by Josh Tynjala.
A even simpler alternative that also works for me is just:
var actualRuntimeType:Class = yourInstance["constructor"];
The runtime is entirely capable of giving you the .constructor, it's just that the compiler complains if you use that syntax. Using ["constructor"] should produce the same bytecode, but the compiler isn't clever enough to stop you.
I included this second because it hasn't been tested anywhere except my current Flash environment, whereas several users have said that the method described above works for them.
If you want to account for inheritance, then you might want to try something like this:
if (objectA is objectB.constructor || objectB is objectA.constructor)
{
// ObjectA inherits from ObjectB or vice versa
}
More generally, if you want to test whether objectA is a subtype of objectB
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
...
if (objectA is getDefinitionByName(getQualifiedClassName(objectB)))
{
...
}
Object obj = new Object();
Object o = new Object();
if(o.getClass().getName().endsWith(obj.getClass().getName())){
return true;
}else{
return false;
}

Resources