Access to Bind Parameters in MyBatis Interceptor - mybatis

How do I read the bind parameters inside a MyBatis Interceptor? I'm trying to extract those information so I can write them to a log table.
The guide (http://www.mybatis.org/mybatis-3/configuration.html) didn't mention how to get them, and the JavaDoc (http://www.mybatis.org/mybatis-3/es/apidocs/org/apache/ibatis/mapping/BoundSql.html) does not have a single line of comment. I saw an example on SO about constructing a new BoundSql but that isn't what I needed.
I tried to test what contents are stored in BoundSql.getParameterMappings() and BoundSql.getParameterObject(), but it seems to be pretty complex. There's JavaType and JdbcType, and if there's only one parameter the ParameterObject isn't a Map object.
What is the proper way to get the bind parameters from BoundSql?

After going through MyBatis source code (where comment is an endangered species), I found out how MyBatis processes the bind parameters. However, that requires access to the JDBC Statement object, which is simply not available inside an Interceptor.
Then I did some testing and settled on this:
If there is only a single parameter, BindSql.getParameterObject() will give you the parameter itself. By using BindSql.getParameterMappings() and ParameterMapping.getJavaType() I can tell which Java class the parameter is.
If there are more than one parameter, BindSql.getParameterObject() will return an instance of org.apache.ibatis.binding.MapperMethod.ParamMap, which extends HashMap, or it will be an instance of the DTO you used. Using .getProperty() from ParameterMapping as key or as getter name, you can process the bind parameters one by one.
If anyone has a better way to do this, I'm all ears.

Related

Is it possible to get the type of a variable while computing completion suggestions?

I'm thinking of creating a VSCode extension to help people use a library I am creating. I've looked in 50 places and can only see documentation on getting the plain text of the document in which the completion suggestions are triggered.
My library exposes a function with two parameters, both objects with the same keys, but the first one will be defined already and the 2nd one will be passed in as an object literal. For example
const obj1 = {a:1, b:2};
doLibraryThing(obj1, {a:[], b:[]});
I want to provide code completion, or a snippet, or anything that can detect that doLibraryThing is being called, and know what properties were defined in obj1, even though usually it will be imported from another file; and then use those properties to generate the suggestion with the same properties, {a:[], b:[]}.
Is this possible?

Node.CloneNode() not a function -dom-to-image.js

I want to create a .png file of a HTML page in angularjs and download it. For this I'm currently using dom-to-image.js and using the domToImage.toBlob function and passing the node element to it. But internally when it goes to dom-to-image.js it throws the error:
node.cloneNode() is not a function
Can anyone please assist me here?
Thanks
This error arises when you attempt to call cloneNode() on anything other than a single DOM node.
In this case, the error is coming from the dom-to-image library, which calls that method internally.
Note that without a code snippet, its hard to identify the precise issue with your code, but the point is, when you call domtoimage.toBlob(), you need to supply a single DOM node.
So double check what you are calling it with. If you are selecting by class, for instance, you could end up with more than one element.
Its best practice to be precise with which node you want to convert to a blob - use the id attribute, like this:
domtoimage.toBlob(document.getElementById('element')).then(...)
where element is the id of your target node.
Its also possible you're selecting with angular.element() or even using jQuery directly.
In both cases, this returns an Object -- which you can't call cloneNode() on.
Also note the following from the Angular docs for angular.element():
Note: All element references in AngularJS are always wrapped with jQuery or jqLite (such as the element argument in a directive's compile / link function). They are never raw DOM references.
Which means you would observe the same behavior in both cases, e.g. both of these:
domtoimage.toBlob($('#element')).then(...)
domtoimage.toBlob(angular.element('#element')).then(...)
would result in the error you see. You can index the Object before supplying it to domtoimage.toBlob(), perhaps like this:
domtoimage.toBlob($('#element')[0]).then(...)
domtoimage.toBlob(angular.element('#element')[0]).then(...)
and that would also work.
Also check out this post about "cloneNode is not a function".

Powershell: Dynamically gather data types for IIS configuration element validation

I'm attempting to dynamically use the Microsoft.Web.Administration namespace within a powershell cmdlet.
Is there a way to add a variable into a Namespace.Class declaration.
I'm using the namespace [Microsoft.Web.Administration] and it's class [Microsoft.Web.Administration.ApplicationPool], it has a property under it 'Recycling' that you can access using a GetProperty method.
[Microsoft.Web.Administration.ApplicationPool].GetProperty("Recycling")
If you spit out the PropertyType of the above using this
[Microsoft.Web.Administration.ApplicationPool].GetProperty("Recycling").PropertyType.FullName
You get this result,
Microsoft.Web.Administration.ApplicationPoolRecycling
which is another class. I now want to access this class dynamically within the cmdlet. How do access this class from within the code, I want the code to dynamically discover the new class of the object and then access that class. But I can't find a way to accomplish this.
Psuedocode for what I'm trying
[System.Reflection.Assembly]::LoadFrom( "C:\windows\system32\inetsrv\Microsoft.Web.Administration.dll" )
$appPoolProperty = [Microsoft.Web.Administration.ApplicationPool].GetProperty($Property)
$subClassName = $appPoolProperty.PropertyType.FullName
#This is the step I'm lost on
$subClass = New-Object $subClassName
So I'm not sure if there's a way to have a TypeName for an object put in as a string value and I can't seem to find a way to cast the variable as anything else. Sorry if this is remedial, I'm a basement grown coder and just learn things as I go.
EDIT: As requested by Mathias below in the comments, an overview of what I'm trying to achieve.
I have a script that automates the configuration of many IIS components. At this time I'm attempting to add validation to the cmdlet Set-AppPoolConfiguration that I've created that allows a configuration to be fed into the cmdlet that configures an AppPool (this is used to deploy websites/weapplications throughout a distributed web environment). Utilizing the details inside the Microsoft.Web.Administration I'm able to get enum values, as well as types of the many configuration components of an AppPool. This is saving me time to where I don't have to hard code in the data types and can just dynamically discover them and do validation on the values when the specific configuration element is chosen.
For example. If an AppPool Recycle schedule is need to be configured, I need to validate it against a TimeSpan data type. If it is not a TimeSpan data type issues will arise when being added to the ScheduleCollection. So I'm looking to validate the value provided before attempting to add it.
Since there are many AppPool configuration elements, I don't want to have to create a massive switch or if/elseif chain that checks each configuration element and statically dictate what data type it is for validation. I want the class itself to dynamically provide this information to simplify the code.
I can get the majority of these data types by simply accessing the property chain within the namespace. For example, if you want to know what type is required for the QueueLength, use this:
[Microsoft.Web.Administration.ApplicationPool].GetProperty("QueueLength").PropertyType.Name
And you'll get Int64.
It's also extremely useful for getting enums.
[Microsoft.Web.Administration.ApplicationPool].GetProperty("ManagedPipelineMode").PropertyType.GetEnumNames()
However attempting this with Schedule and you run into a small issue as it returns ScheduleCollection. This is true of any of the configuration elements that are part of a collection.
[Microsoft.Web.Administration.ApplicationPool].GetProperty("Recycling").PropertyType.GetProperty('PeriodicRestart').PropertyType.GetProperty('Schedule').PropertyType.Name
However the knowledge that the schedule item inside the ScheduleCollection is only accessible from within the Schedule class. My code currently checks to see if it is a collection, and then if it is, it is attempting to access that collection/class and get the information that is required. To find out that schedule is a TimeSpan you have to access it's specific class instance:
[Microsoft.Web.Administration.Schedule].GetProperty('Time').PropertyType.Name
Now AppPools are simple, there's only a single collection group that is normally edited, so hard coding in that if you're attempting to set a new recycle schedule it will be a TimeSpan isn't that big of a deal, however when we move over to WebSite/WebApplication configurations, it becomes more tedious to statically declare data types for each configuration element that is part of a collection, and becomes more useful to try and discover these dynamically based on the configuration element selected.
This was my initial approach, I just included the above for clarity. I'm going to step back and take another look at how to attack this as this does not appear to be as easy as I had hoped, I'll post my solution here.
You can retrieve the constructor from the type literal and invoke it like so:
$type = [Microsoft.Web.Administration.ApplicationPoolRecycling]
$ctor = $type.GetConstructor('NonPublic,Instance',$null,#(),$null)
$appPoolRecyclingInstance = $ctor.Invoke($null)
Though there may be a way to do the above, in order to complete the updates to my cmdlet and proceed forward with my project I went a hybrid route.
The reason why I started exploring the [Microsoft.Web.Administration] namespace was that it provided information on the data types where the typical way I was manipulating IIS settings failed using Get/Set/Add-WebConfigurationProperty.
The specific failure is in reporting back valid data types for Enums. Take for instance ProcessModel.IdentityTypes. There is a set of valid entries for an IdentityType. However the following doesn't provide you with those valid types, so you either have to create static instances of them inside your cmdlet, or some other external data source, whereas I wanted Microsoft to provide them either through IIS itself, or through the classes attached to these configuration elements so the cmdlet would need minimal updating as IIS versions/configuration elements change.
This code returns Boolean
(Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/applicationPools/add[#name='$AppPool']" -name "AutoStart").Value.GetType().Name
However, this code returns string, which is true, but I needed to know that it is an enum and I needed to know the proper values.
(Get-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/applicationPools/add[#name='$AppPool']" -name "processModel").identityType.GetType().Name
Using a mix of both the Namespace and the traditional Get-WebConfigurationProperty commands I can successfully now test for data types, as well as gather proper values for enums dynamically in code. If there is interest I can post the entire validation code here that I'm using for this cmdlet.

Issue: Action redirect do not include parameter as complex objects in Struts2?

I have tried an example in which i have inserted a user using insert method of UserAction class.
On insert I have redirected the success to loadAdd method of UserAction.
During redirect I have passed the parameter as
${user}
In struts 2.0.14 this gives an ognl exception.
whereas when I pass
${user.id}
it works.
My observation says this is a bug in struts or ognl that it does parse composite objects while it parses simple data types.
Any work-around please suggest.
Or
Is there any way by which I can forward the complete action context or value stack in the redirected action
It's not a bug.
Struts2 uses a type conversion system to convert between Strings (native HTTP) and other objects. It has default type converters for all of the standard primitives, boxed primitives, collections, maps, etc. If you want to allow Struts2 to automatically convert between a string and your User class, you need to create a type converter for it. Otherwise, you can use ${user.id}, which is a primitive or boxed primitive.
http://struts.apache.org/2.2.3/docs/type-conversion.html
Also, the ValueStack is per-request, so when you redirect and create a new request, the previous requests ValueStack is no longer available.

Castle Windsor - Null constructor argument

How can I pass a null constuctor argument using Castle Windsor? I thought the following would work
<parameters>
<repository>null</repository>
<message>null</message>
</parameters>`
If you want them to be null, it means that they are non-essential dependencies. By having them as ctor arguments you suggest otherwise. You should redesign your class to have another constructor that takes only essential dependencies, if you wish that they not change throughout the lifetime of an object (be readonly), or expose them as properties.
With Windsor you can't make it to pass nulls, for reasons mentioned in the other answer.
Wouldn't it better to simply have an additional public constructor that doesn't take these parameters, then you wouldn't need to register the parameters in the config?
This was discussed a while back on the mail list, and at the time I looked into the code. Null values are deliberately filtered out (mainly because the complicate type resolution).
I couldn't find a simple way to make a special case to add them.