Janino Compile Exception : UDJC step - pentaho

Thanks in advance for your support.
In UDJC step, the following code gives me Janino exception,
In processRow method
Hashtable hastable=getConfigData() // This method return Hashtable
Set set=hashtable.get("ERROR_2001").keySet(); ---> //hashtable.get("ERROR_2001"), This returns another hashtable
Exception:
A method named "keySet" is not declared in any enclosing class nor any supertype, nor through a static import
In forums I could not find the turn around solution to fix this. I am using JDK 1.7 and PDI 5.1 (latest download)

AFAIK, you can't use generics in Janino, so Janino can not determine exact class of the object returned by hashtable.get("ERROR_2001") method, so it assumes that Object is returned, which has no keySet() method defined.
Try to cast the result of hashtable.get("ERROR_2001") to the value class, contained in your hashtable collection:
Hashtable errorEntry = (Hashtable) hashtable.get("ERROR_2001");
Set set = errorEntry.keySet();

Related

Kotlin: Method reference not working?

It seems I'm unable to use a method reference of an object in Kotlin. This feature exists in Java.
For example in Java if I was looping through a string to append each character to a writer:
string.forEach(writer::append);
But in Kotlin using the same syntax does not work because:
For now, Kotlin only supports references to top-level and local functions and members of classes, not individual instances. See the docs here.
So, you can say Writer::append and get a function Writer.(Char) -> Writer, but taking a writer instance and saying writer::append to get a function (Char) -> Writer is not supported at the moment.
Starting from Kotlin 1.1 writer::append is a perfectly valid bound callable reference.
However, you still cannot write string.forEach(writer::append) because Writer#append method returns a Writer instance and forEach expects a function that returns Unit.
I am using Kotlin 1.3 and while referencing a Java method I got a very similar error. As mentioned in this comment, making a lambda and passing it to the forEach method is a good option.
key.forEach { writter.append(it) }
Being it the implicit name of a single parameter.

Ninject Cascading Constructor Arguments

I have a type IRoleRepository which accepts a constructor argument "database" which accepts a type of IDbRepository which itself takes a constructor argument "ConnectionStringName". I have a dependency resolver which has a GetService method and while the following code works I was hoping there would be better way to do this at Bind time vs at Get time with Ninject 3.0. Note I may have multiple IDBRepository instances each with their own "ConnectionStringName".
_repository = EngineContext.Current.GetService<IRoleRepository>(
new ConstructorArgument("database",
EngineContext.Current.GetService<IDbRepository>(
new ConstructorArgument(SystemConstants.ConnectionStringName, SystemConstants.ConfigurationDatabase))));
You can use WithConstructorArgument to specify the constructor arguments together with the binding.
kernel.Bind<IDbRepository>().To<DbRepository>()
.WithConstructorArgument(
SystemConstants.ConnectionStringName,
SystemConstants.ConfigurationDatabase);
or use ToConstructor()
kernel.Bind<IDbRepository>().ToConstructor(
x => new DbRepository(
SystemConstants.ConfigurationDatabase,
x.Inject<ISomeOtherDependency>())
OK I believe I found what I wanted:
By using this at Bind Time:
Bind<IDbRepository>().To<SqlServerRepository>()
.WhenInjectedInto<IRoleRepository>()
.WithConstructorArgument(SystemConstants.ConnectionStringName, SystemConstants.ConfigurationDatabase);
This allows me to use this at Get time:
_repository = EngineContext.Current.GetService<IRoleRepository>();
This of course means I can now vary the constructor argument for IDbRepository based upon the more specific repository which the IDbRepository is being injected. eg:
Bind<IDbRepository>().To<SqlServerRepository>()
.WhenInjectedInto<ITimerJobStore>()
.WithConstructorArgument(SystemConstants.ConnectionStringName, SystemConstants.ConfigurationDatabase);
Bind<ITimerJobStore>().To<TimerJobSqlStore>();

DateTime.Today Error

In VS2010 for a VB.NET 4.0 project, the IDE puts a green line under the last line in the following code:
Dim cityLocal As DateTime
cityLocal = externalFunction()
cityLocal.Today()
The suggested code replace is to update 'cityLocal' with 'Date'. The reason is:
Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
But it does compile and does work correctly. Is this just a bug in the VS2010?
Today is a shared member, thus should not (but can) be accessed through an instance of DateTime change your code to.
DateTime.Today
Although Visual Studio gives you suggestions to correct the "Error" it is infact a compiler warning, warning you that there is no need for an instance to access the shared member. You'll find that it is not listed as an error in the error list. Which is why it compiles correctly.
The Visual Basic language specification states
9.2.4 Shared Methods
The Shared modifier indicates a method
is a shared method. A shared method
does not operate on a specific
instance of a type and may be invoked
directly from a type rather than
through a particular instance of a
type. It is valid, however, to use an
instance to qualify a shared method.
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=01EEE123-F68C-4227-9274-97A13D7CB433:
More information on the warning can be found in the documentation.
http://msdn.microsoft.com/en-us/library/y6t76186.aspx
Date.Today is a static (Shared in VB.NET) property. You are able to use it from an instance because the compiler knows to make the proper call, but it is not the expected usage pattern, which is both unnecessary and undesirable to use directly from an instance.
As a static variable, you should use Date.Today rather than variable.Today.
Today is a shared/static member. Normally you would use DateTime.Today not your instance variable.
http://msdn.microsoft.com/en-us/library/system.datetime.today.aspx

Sub New() is not accessible in this context because it is 'Friend'

So what does this mean and how do I fix it?
This message occurs if I place the New keyword in the line(s) below. If I remove it, i get an error at runtime saying I need to use New. What am I doing wrong?
Dim oPS As AeccPointStyle = New AeccPointStyle
ops = oDescKey.PointStyle
Debug.Print(oPS.Name)
Debug.Print(oPS.MarkerSymbolName)
Also tried
Dim oPS As New AeccPointStyle
ops = oDescKey.PointStyle
Debug.Print(oPS.Name)
Debug.Print(oPS.MarkerSymbolName)
Thanks!
Update 1 - based on comment from Meta-Knight
1 -
Dim oPS As AeccPointStyle = Nothing
oPS = oDescKey.PointStyle
2 -
Dim oPS As AeccPointStyle = oDescKey.PointStyle
Both versions throw NullReferenceExceptions.
The empty constructor of AeccPointStyle is marked as friend, which means only classes inside its assembly can call it.
But looking at your code, I don't think you need to call New. Just set it to Nothing at first. Or even better, directly set your variable with the good value:
Dim oPS As AeccPointStyle = oDescKey.PointStyle
Edit about your NullReferenceException:
Typically, this type of exception is raised when you call a property of an object with a value of Nothing. In this case, if oDescKey was set to Nothing, such an exception would be raised.
If oDescKey does NOT have a value of Nothing, then the only thing that executes some code is the PointStyle property. So it's safe to assume that the PointStyle property throws a NullReferenceException. Try watching the oDescKey.PointStyle variable in the debugger, you should see that it throws an exception.
If your AeccPointStyle class is using a 'Friend' modifier,
ie it is defined as:
Friend Class AeccPointStyle
or the default constructor has the 'Friend' modifier,
ie:
Friend Sub New()
and the code you posted is not in the same assembly, you cannot call the constructor on this class. In order to get this to work, you must put your code in the same assembly as the AeccPointStyle class. Check out this page to learn more about the modifiers: more information about modifiers
My guess is the following: AeccPointStyle is declared in another assembly than the code sample in your question. The constructor (Sub New) of AeccPointStyle is declared a Friend, which means that it is reachable only within the same assembly.
You can solve this in two ways
Change Sub New so that it is Public
Provide a Shared Public Sub Create, that will create and return a new AeccPointStyle
AeccPointStyle doesn't have a public default constructor. The one you're trying to use is limited to other classes within the same assembly.
Here's some code I found online:
Dim oPointStyle As AeccPointStyle
Set oPointStyle = g_oAeccDoc.PointStyles.Add(strName)
Notice the PointStyles property (probably some sort of PointStylesColleciton) on g_oAeccDoc is instantiating and returning a new AeccPointStyle instance for you.
When using FRIEND as access modifier for your class, you need to make sure that both the class it-self and the class where you use it are in the same NAMESPACE, otherwise you will get this error message.
For other people encountering this issue, I had to do a one-way upgrade for an old project we were referencing. It upgraded it to .NET 4.0 as well, when it was 2.0/3.5. That caused the (also old) project that was an older version to get this error when referencing it. Changing the newly upgraded version back to .NET 3.5 did the trick for me. It's a very non-descript error!

Java: Why method type in .class file contains return type, not only signature?

There is a "NameAndType" structure in the constants pool in .class file.
It is used for dynamic binding.
All methods that class can "export" described as "signature + return type".
Like
"getVector()Ljava/util/Vector;"
That breakes my code when return type of the method in some .jar is changed, even if new type is narrower.
i.e:
I have the following code:
List l = some.getList();
External .jar contains:
public List getList()
Than external jar changes method signature to
public ArrayList getList().
And my code dies in run-time with NoSuchMethodException, because it can't find
getList()Ljava/util/List;
So, I have to recompile my code.
I do not have to change it. Just recompile absolutely the same code!
That also gives ability to have two methods with one signature, but different return types! Compiler would not accept it, but it is possible to do it via direct opcoding.
My questions is why?
Why they did it?
I have only one idea: to prevent sophisticated type checking in the runtime.
You need to look up to the hierarchy and check if there is a parent with List interface.
It takes time, and only compiler has it. JVM does not.
Am I right?
thanks.
One reason may be because method overloading (as opposed to overriding) is determined at compile time. Consider the following methods:
public void doSomething(List util) {}
public void doSomething(ArrayList util) {}
And consider code:
doSomething(getList());
If Java allowed the return type to change and did not throw an exception, the method called would still be doSomething(List) until you recompiled - then it would be doSomething(ArrayList). Which would mean that working code would change behavior just for having recompiled it.