Converting Map to Java Bean, some properties cannot be set rightly - dictionary

// I use this simple program:
public static Object convertToBean(Class type, Map map) {
BeanInfo beanInfo;
Object obj = null;
try {
beanInfo = Introspector.getBeanInfo(type);
obj = type.newInstance();
// When I debugging to here, I found that some properties is different from the variable the Object own. PropertyDescriptor changes charactor case when the variable is not in "String" type.
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor descriptor : propertyDescriptors) {
String propertyName = descriptor.getName();
if (map.containsKey(propertyName)) {
Object value = map.get(propertyName);
Object[] args = new Object[1];
args[0] = value;
descriptor.getWriteMethod().invoke(obj, args);
}
}
} catch (Exception ignored) {
}
return obj;
}
//Using BeanMap is the same question.

Finally I found the root cause.
The problem solved by changing “A01” to "a01".
The variable name must be strict camel rule. First character must be lower case, except first two characters are all in upper case, like "AD".
Because the setter and getter methods will generate in same pattern. so It'll be difficult to recognize the real name of one variable.

Related

How to get parameter name in aspectj advice class?

I am asking this question with my limited knowledge of java reflection and AOP.
Background:
I am using annotation based advice in my Java 7 application. Further to get the method parameter which I need to use in my advice I am using spring EL. See below examples:
In first example i want to use second parameter to do my work, whereas in second example I am using a POJO and want to use its "id" field.
#MyAnnotation(param = "args[1]")
public void someMethod(int param1, String param2) {
return null;
}
#MyAnnotation(param = "args[0].id")
public void someMethod(SomeObject someObject) {
return null;
}
But what I actually want is, to get my hands on the parameter names in my AOP. So that I can use #MyAnnotation(param = "param1") or #MyAnnotation(param = "someObject.id") instead.
From what I have known, you can not get parameter name using reflection. But recently I came across Spring cache abstraction(link), where I see:
#Cacheable(cacheNames="books", key="#isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
Can someone put some light here, how I can achieve similar behavior.
See MethodBasedEvaluationContext and ParameterNameDiscoverer.
CacheEvaluationContext is a subclass of MethodBasedEvaluationContext.
Code here...
// Expose indexed variables as well as parameter names (if discoverable)
String[] paramNames = this.parameterNameDiscoverer.getParameterNames(this.method);
int paramCount = (paramNames != null ? paramNames.length : this.method.getParameterCount());
int argsCount = this.arguments.length;
for (int i = 0; i < paramCount; i++) {
Object value = null;
if (argsCount > paramCount && i == paramCount - 1) {
// Expose remaining arguments as vararg array for last parameter
value = Arrays.copyOfRange(this.arguments, i, argsCount);
}
else if (argsCount > i) {
// Actual argument found - otherwise left as null
value = this.arguments[i];
}
setVariable("a" + i, value);
setVariable("p" + i, value);
if (paramNames != null) {
setVariable(paramNames[i], value);
}
}

WF 4 Rehosted Designer - get foreach InArgument Value

After reading this article:
http://blogs.msdn.com/b/tilovell/archive/2009/12/29/the-trouble-with-system-activities-foreach-and-parallelforeach.aspx
I have defined the ForEachFactory as follows:
public class ForEachFactory<T> : IActivityTemplateFactory
{
public Activity Create(DependencyObject target)
{
return new ForEach<T>
{
DisplayName = "ForEachFromFactory",
Body = new ActivityAction<T>
{
Argument = new DelegateInArgument<T>("item")
}
};
}
}
All works well but is it possible to check how that DelegeateInArgument in my case named "item" changes its value ?
So if i have defined an array in the variables section and initialized with
{1, 2, 3} i need a way to check how the "item" takes value 1, 2 and then 3.
To be more accurate, i've added this pic, with a breakpoint on the WriteLine activity inside the foreach. When the execution will stop there, is there a way to find out what the value of item is ?
EDIT 1:
Possible solution in my case:
After struggling a bit more i found one interesting thing:
Adding one of my custom activities in the Body of the ForEach, i am able to get the value of the item like this :
So, my activity derives from : CodeActivity
Inside the protected override String[] Execute(CodeActivityContext context) i am doing this job.To be honest, this solves the thing somehow, but it is doable only in my custom activities. If i would put a WriteLine there for example, i would not be able to retrieve that value.
you can access the DelegeateInArgument of a ForEach activity by inspecting the ModelItem trees parent and checking for DelegeateInArgument's. If you need a specific code example to achieve this I may need a some time to code the example. As it has been a long time since I did this, see my question i asked over on msdn
So basically where your break point is, you can access the variable values as these are defined with n the scope of your activity as 'variables'. However the 'item' variable is actually only accessible from the parent loop activity. So you have to get the model item of the current executing activity and then traverse up the tree to find the parent containing the desired DelegateInArgument.
Can you flesh out exactly what you want to achieve? Is it that when your debugging the workflow in the re-hosted designer you want to display the variable values to the user as they change in the UI?
Edit - added tracking example
So as your wanting to display the variable values during execution of the workflow we need to use tracking to achieve this. In the example your using the author has already implemented some basic tracking. So to achieve the extended variable tracking you want you will need to alter the tracking profile.
Firstly amend the WorkflowDesignerHost.xaml.cs file alter the RunWorkflow method to define the SimulatorTrackingParticipant as below.
SimulatorTrackingParticipant simTracker = new SimulatorTrackingParticipant()
{
TrackingProfile = new TrackingProfile()
{
Name = "CustomTrackingProfile",
Queries =
{
new CustomTrackingQuery()
{
Name = all,
ActivityName = all
},
new WorkflowInstanceQuery()
{
**States = {all },**
},
new ActivityStateQuery()
{
// Subscribe for track records from all activities for all states
ActivityName = all,
States = { all },
**Arguments = {all},**
// Extract workflow variables and arguments as a part of the activity tracking record
// VariableName = "*" allows for extraction of all variables in the scope
// of the activity
Variables =
{
{ all }
}
}
}
}
};
This will now correctly capture all workflow instance states rather than just Started/Completed. You will also capture all Arguments on each activity that records tracking data rather than just the variables. This is important because the 'variable' were interested in is actually (as discussed earlier) a DelegateInArgument.
So once we have changed the tracking profile we also need to change the SimulatorTrackingParticipant.cs to extract the additional data we are now tracking.
If you change the OnTrackingRecordReceived method to include the following sections these will capture variable data and also Argument data during execution.
protected void OnTrackingRecordReceived(TrackingRecord record, TimeSpan timeout)
{
System.Diagnostics.Debug.WriteLine(
String.Format("Tracking Record Received: {0} with timeout: {1} seconds.", record, timeout.TotalSeconds)
);
if (TrackingRecordReceived != null)
{
ActivityStateRecord activityStateRecord = record as ActivityStateRecord;
if (activityStateRecord != null)
{
IDictionary<string, object> variables = activityStateRecord.Variables;
StringBuilder vars = new StringBuilder();
if (variables.Count > 0)
{
vars.AppendLine("\n\tVariables:");
foreach (KeyValuePair<string, object> variable in variables)
{
vars.AppendLine(String.Format(
"\t\tName: {0} Value: {1}", variable.Key, variable.Value));
}
}
}
if (activityStateRecord != null)
{
IDictionary<string, object> arguments = activityStateRecord.Arguments;
StringBuilder args = new StringBuilder();
if (arguments.Count > 0)
{
args.AppendLine("\n\tArgument:");
foreach (KeyValuePair<string, object> argument in arguments)
{
args.AppendLine(String.Format(
"\t\tName: {0} Value: {1}", argument.Key, argument.Value));
}
}
//bubble up the args to the UI for the user to see!
}
if((activityStateRecord != null) && (!activityStateRecord.Activity.TypeName.Contains("System.Activities.Expressions")))
{
if (ActivityIdToWorkflowElementMap.ContainsKey(activityStateRecord.Activity.Id))
{
TrackingRecordReceived(this, new TrackingEventArgs(
record,
timeout,
ActivityIdToWorkflowElementMap[activityStateRecord.Activity.Id]
)
);
}
}
else
{
TrackingRecordReceived(this, new TrackingEventArgs(record, timeout,null));
}
}
}
Hope this helps!

How do you make a class method modify itself?

asp.net C#4
I have a simple class to working with query strings.
A new instance is created like this:
public QueryString(string querystring)
{
try
{
_table = new Hashtable();
if (querystring.Length > 0)
{
foreach (string pair in querystring.Split('&'))
{
string[] item = pair.Split('=');
_table.Add(item[0].ToLower(), item[1]);
}
}
}
catch (Exception)
{
}
}
I want to add a method to this that will remove a key value pair. I don't want it to return a new querystring, I just want it to remove the pair from the current instance. Not sure how to do that since it says I can't assign a value to 'this'
public void Remove(string key)
{
String querystring = this.ToString();
try
{
_table = new Hashtable();
if (key.Length > 0)
{
foreach (string pair in querystring.Split('&'))
{
string[] item = pair.Split('=');
if (item[0] != key)
{
_table.Add(item[0].ToLower(), item[1]);
}
}
this = _table;
}
}
catch (Exception)
{
}
}
You're overcomplicating things. Since your class's state is made up of the _table field, all you need to do is remove the item with the given key from that field.
The following example replaces your untyped Hashtable wit a strongly-typed Dictionary. I also chose to initialize the dictionary with a LINQ statement, but you could keep your old code there if you prefer.
public class QueryString
{
private readonly Dictionary<string, string> _table;
public QueryString(string querystring)
{
if (querystring.Length > 0)
{
var pairs =
from pair in querystring.Split('&')
let item = pair.Split('=')
select new {key = item[0], value = item[1]};
_table = pairs.ToDictionary(p => p.key, p => p.value);
}
}
public void Remove(string key)
{
_table.Remove(key);
}
}
You cannot assign a value to this since it is a reference to the object itself.
However, if you remove the line this = _table; , isn't things working as they should then? I guess your ToString() is somewhat using the hashtable to generate a "printer friendly" QueryString, and if that is the case, the way I see it, your Remove() method should be working (since you are replacing the _table variable with a new HashTable not including the key-value pair you want to exclude).
you are passing a querystring into the class so the original querystring IS intact.
However you then break down the querystring into a a Hashtable of key/value pairs. If you want to keep THAT intact you need to clone the HashTable and perform the remove on the clone.
In any case it's probably a good idea to keep the querystring you are passing in as a constructor parameter in a member variable for safe keeping.

Pass property from controller to Model

I am trying to pass a variable from a method in my Controller to a method in a Model. Since the method in the Model takes one argument (which was designed earlier), I cannot pass my variable as an argument to the method in the Model. And also, the method in this Model is called by other controllers too, so if I change the argument, I have to change all the controllers too, which would be a tedious task.
What I have been trying so far is- I created one MyVariableClass and declared a property. Then I instantiated that class and set the property string to the variable that I wanted to pass. Now, in my Model's method, I instantiated the same MyVariableClass again, but when I did that, the value of the variable was set to null. The code I have right now is -
public ActionResult ItemInformation( string id)
{
//Pass a string to MyVariable
MyVariableVClass params = new MyVariableClass();
params.myVariable = "abc";
//This is what My Model is taking as an argument(id), and I don't want to
//pass mYvariable along with that argument because it will break other controllers
// too which calls this method
var itemInformation = _repository.GetItemInformation(id);
return View(itemInformation);
}
and MyVariableClass
public class MyVariableClass
{
public string myVariable { get; set; }
}
and the method in My Model
public IList<Items> GetItemInformation(string itemId)
{
MyVariableClass webType = new MyVariableClass();
var _params = webType.myVariable;
//Check this variable and perform database query
if (_params =="this")
{
var query = myFirstQuery;
}
else
{
var query = mySecondQuery;
}
//return ....
}
Anybody has solution to this? Thanks in Advance!
Any reason why subclassing your model and overriding the GetItemInformation method wouldn't work? Or, even easier, why not just overload the GetItemInformation method with one that takes two strings? Your other controllers can still use the one that only takes a single string.
public IList<Items> GetItemInformation(string itemId, MyVariableClass webType)
{
var _params = webType.myVariable;
//Check this variable and perform database query
if (_params == "this")
{
var query = myFirstQuery;
}
else
{
var query = mySecondQuery;
}
//return ....
}
public IList<Items> GetItemInformation(string itemId)
{
MyVariableClass fauxType = new MyVariableClass();
fauxType.myVariable = "not this";
return GetItemInformation(itemId, fauxType);
}
Try using session variable.

Is it possible to define a generic type Vector in Actionsctipt 3?

Hi i need to make a VectorIterator, so i need to accept a Vector with any type. I am currently trying to define the type as * like so:
var collection:Vector.<*> = new Vector<*>()
But the compiler is complaining that the type "is not a compile time constant". i know a bug exists with the Vector class where the error reporting, reports the wrong type as missing, for example:
var collection:Vector.<Sprite> = new Vector.<Sprite>()
if Sprite was not imported, the compiler would complain that it cannot find the Vector class. I wonder if this is related?
So it looks like the answer is there is no way to implicitly cast a Vector of a type to valid super type. It must be performed explicitly with the global Vector.<> function.
So my actual problem was a mix of problems :)
It is correct to use Vector. as a generic reference to another Vector, but, it cannot be performed like this:
var spriteList:Vector.<Sprite> = new Vector.<Sprite>()
var genericList:Vector.<Object> = new Vector.<Object>()
genericList = spriteList // this will cause a type casting error
The assignment should be performed using the global Vector() function/cast like so:
var spriteList:Vector.<Sprite> = new Vector.<Sprite>()
var genericList:Vector.<Object> = new Vector.<Object>()
genericList = Vector.<Object>(spriteList)
It was a simple case of me not reading the documentation.
Below is some test code, I would expect the Vector. to cast implicitly to Vector.<*>.
public class VectorTest extends Sprite
{
public function VectorTest()
{
// works, due to <*> being strictly the same type as the collection in VectorContainer
var collection:Vector.<*> = new Vector.<String>()
// compiler complains about implicit conversion of <String> to <*>
var collection:Vector.<String> = new Vector.<String>()
collection.push("One")
collection.push("Two")
collection.push("Three")
for each (var eachNumber:String in collection)
{
trace("eachNumber: " + eachNumber)
}
var vectorContainer:VectorContainer = new VectorContainer(collection)
while(vectorContainer.hasNext())
{
trace(vectorContainer.next)
}
}
}
public class VectorContainer
{
private var _collection:Vector.<*>
private var _index:int = 0
public function VectorContainer(collection:Vector.<*>)
{
_collection = collection
}
public function hasNext():Boolean
{
return _index < _collection.length
}
public function get next():*
{
return _collection[_index++]
}
}
[Bindable]
public var selectedItems:Vector.<Category>;
public function selectionChange(items:Vector.<Object>):void
{
selectedItems = Vector.<Category>(items);
}
I believe you can refer to an untyped Vector by just calling it Vector (no .<>)
With Apache Flex 4.11.0, you can already do what you want. It might have been there since 4.9.0, but I have not tried that before.
var collection:Vector.<Object> = new Vector.<Object>()
maybe?
But i'm just speculating, haven't tried it.
var collection:Vector.<Object> = new Vector.<Object>()
but only on targeting flash player 10 cs4

Resources