From ExecutableType we can inspect the types of parameters using getParameterTypes(). However, I cannot find a mechanism to inspect the parameter names.
I understand that in <= Java 7 the parameter names are not retained in the bytecode. However, I would still expect to be able to access the argument names arg0, arg1.
If the compiler is a Java 8 compiler running with the -parameters flag I would expect to get the original parameter names from the source code.
Is there a mechanism that I am overlooking? It seems strange that we are able to query this using the reflection API using Parameter.getName() if we are not capable of retrieving this information whilst annotation processing.
Instead of ExecutableType, use ExecutableElement. From this you can get it's parameters which should all have names. You can convert using Types.asElement.
Related
Using Data Fusion Argument Setter, I've defined all parameters in it for a reusable pipeline. While executing it, I provide runtime arguments for some parameters which are different from default arguments provided in the JSON URL embedded in Argument Setter.
But a number of times, the pipeline ends up taking the default values from Argument Setter URL instead of Runtime Arguments causing failures.
This behavior is not consistent in every pipeline I create - which confirms that Runtime arguments are supposed to supersede any prior value defined for an argument.
The workarounds I use is by deleting the plugin and re-adding it for every new pipeline. But that defeats the purpose of creating a re-usable pipeline.
Has anyone experienced this issue ?
Current Runtime Options
This wiki https://cloud.google.com/data-fusion/docs/tutorials/reusable-pipeline provides the sample of how to create re-usable pipeline using Argument Setter. From there, it seems like the runtime arguments was used to notify the data fusion pipeline to use the macro from Argument Setter URL. Argument Setter is a type of Action plugin that allows one to create reusable pipelines by dynamically substituting the configurations that can be served by an HTTP Server. It looks like no matter how you change the runtime arguments, as long as long the same marco can be read when pipeline is running, the arguments will be override.
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.
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.
I'm trying to use PowerShell to call some F# code which uses Akka.Net actors.
The F# code works fine in unit testing and when run from the F# interpreter, but when I call the same code from a PowerShell cmdlet I get the following exception:
System.MissingMethodException: Method not found: 'Void Nessos.FsPickler.BinarySerializer..ctor(Microsoft.FSharp.Core.FSharpOption`1<Boolean>,
Microsoft.FSharp.Core.FSharpOption`1<Nessos.FsPickler.ITypeNameConverter>)'.
at Akka.FSharp.Serialization.ExprSerializer..ctor(ExtendedActorSystem system)
at Akka.FSharp.Serialization.exprSerializationSupport(ActorSystem system)
at Namespace.NewActorCmdlet..ctor(Host hostA, Host hostB, Boolean option, UserDetails user) in
E:\Projects\Namespace\NewActorCommand.fs:line 24
at Namespace.StartNewActorCommand.ProcessRecord() in
E:\Projects\Namespace\StartNewActor.fs:line 67
at System.Management.Automation.CommandProcessor.ProcessRecord()
I tried running [Nessos.FsPickler.BinarySerializer]::new.OverloadDefinitions in that PowerShell session to check what methods PS though was available and I get:
Nessos.FsPickler.BinarySerializer new(Microsoft.FSharp.Core.FSharpOption[bool] forceLittleEndian, Microsoft.FSharp.Core.FSharpOption[Nessos.FsPickler.ITypeNameConverter] typeConverter)
First thing I noticed was that the version shown by PowerShell takes an FSharpOption[bool] instead of FSharpOption[Boolean]. I tried modifying the Akka.FSharp code to explcitly pass an Option, but that didn't seem to help.
I'm using FSharp.Core 4.0.0.1 (other links suggested 3.0 had problems).
Has anyone seen anything similar?
Even suggestions about where to look for the problem would be helpful, I'm not sure if the issue is with PowerShell, F# or Akka.Net.
Powershell can be difficult when it comes to matching methods based on parameter types. I've found that sometimes i have to "trick" PS by passing an expression to a method rather than a PS variable. For example $object.method($something.property) instead of $prop = $something.property; $object.method($prop) has worked for me.
In the case of overloaded methods another thing you can do is use Reflection to make sure you've got the method with the right signature. For example:
$mi=$object.gettype().getmethod('TheMethod',#([typeParm1],[typeParm2]))
$mi.invoke($object, #($arg1,$arg2))
And sometimes casting helps: $object.method([typeToMatchMethodSig]$arg1) or maybe even a double cast:$object.method([bool][int]$arg1) In both cases I think you'll have more luck if you pass the cast expression as an argument, rather than assign it to a variable and pass the variable.
I doubt this is the case in the OP, but using [activator]::createinstance(...) can be used with a private constructor.
I usually muck around with it till either something works or I give up.
BTW, you can turn on PS tracing for parameter binding and get a lot of info, which may or may not be useful.
I am trying to support the 'duplicate' command. It works fine for duplicating the top class:
tell application "SpellAnalysis" to duplicate level 1
This, however, crashes:
tell application "SpellAnalysis" to duplicate (get unit 1 of (get level 1))
I have provided index specifiers for both classes, where the outer container for 'unit' is 'level'. Oddly, I can specify a property of the unit class like this:
tell application "SpellAnalysis" to (get general rule of unit 1 of (get level 1))
The culprit seems to be that the 'objectsByEvaluatingSpecifier' always returns a null value when used within NSCloneCommand subclass, as well as the unit class' objectSpecifier method, where its needed.
I was finally able to support AppleScript 'duplicate' command. Although the normal way to support the command is by sub-classing 'NSCloneCommand', with this method, your direct parameter results in a specifier that specifies the containing object and not the direct object--as a special provision of the 'NSCloneCommand'. I suppose this is meant to facilitate the case when you would be duplicating an object belonging to a document, where the document class provides the means for creating new constituent objects. Unfortunately, in my case, my constituent objects take part in their own duplication and need to know their specifiers to do so. The solution was to support the 'duplicate' command by the optional technique of creating a custom 'duplicate' command within my application's suite that entailed subclassing the more general 'NSScriptCommand'. This alternative avoids any redirection of the specifier returned from the 'directParameter' method of the 'NSScriptCommand' class. I was able to work from there to derive all the child class-objects for cloning.