Call abstract java class from jruby with a generic - jruby

Currently facing an issue while writing a similar java class in Jruby.
Example:
In Java:
public class Client extends ClientConnection<ChannelType> {
//do some stuff
}
In Jruby:
class Client < Java::'package_name'::ClientConnection
//do some stuff
end
Don't know how to pass ChannelType class in Jruby code while rewriting the Client class

The short version is, you can't unfortunately.
The JRuby wiki explains it as such here (https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby#beware-of-java-generics):
If a Java class is defined with Java generics, the types are erased during compilation for backwards compatibility. As a result, JRuby will have problems with automatic type conversion. For example, if you have a Map, it will be seen as a simple Map, and JRuby will not be able to determine the correct types using reflection.

Related

Class loading collision between Robolectric and Powermock

I'm trying to write a test that needs both Robolectric 2.2 and PowerMock, as the code under test depends on some Android libraries and third party libraries with final classes that I need to mock.
Given that I'm forced to use the Robolectric test runner through:
#RunWith(RobolectricTestRunner.class)
...I cannot use the PowerMock test runner, so I'm trying to go with the PowerMock java agent alternative, without luck so far.
I have setup everything according to this guide but I'm facing a collision problem between classes required by the javaagent library and by robolectric through its dependency with asm-1.4. Both depend on
org.objectweb.asm.ClassVisitor
, but javaagent-1.5.1 ships with its own version where ClassVisitor is an interface while asm-1.4 version for the same namespace is an abstract class, with the corresponding error at runtime:
java.lang.IncompatibleClassChangeError: class org.objectweb.asm.tree.ClassNode has interface org.objectweb.asm.ClassVisitor as super class
I have even tried to modify the javaagent library jar to entirely remove the org.objectew.asm classes in there, but that doesn't work as ClassNotFoundException happens afterwards due to some other classes needed in the org.objectweb.asm package that only ship in the javaagent library jar, and not in the asm one.
Any ideas? According to examples out there the agent seems to work fine with, at least, the Spring test runner.
I had the same problem and while I didn't solve this problem as such, I wanted to share my approach, which removes the need for PowerMock (which is always a good thing in my view): I wanted to mock a call to
Fragment fooFragment = new FooFragment();
So what I did was addanother level of indirection. I created a FragmentProvider class:
public FragmentFactory fragmentFactory = new FragmentFactory();
[...]
Fragment fooFragment = fragmentFactory.getFooFragment();
After i did this, I could just mock out the factory with standard Mockito, like this:
FragmentFactory mockFactory = mock(FragmentFactory.class);
activity.fragmentFactory = mockFactory;
when(mockFactory.getFooFragment()).thenReturn(mockFooFragment);

Jruby rb to java generated class inheritance support or workarounds

I am experimenting around with JRuby - generating java from ruby files. I have an abstract class in ruby that implement a Java interface, and child classes extending this. also in ruby.
I'm running into the problem as described on http://jira.codehaus.org/browse/JRUBY-6342 where all the generated java files only extend RubyObject.
I am wondering if anyone else has encountered this and have a workaround? Right now I have used a java_implement interface in each child class as they do not extend the abstract class.
I have included the snippet from JRUBY-6342 describing the problem:
The Java code generated by jrubyc --java does not appear to support Ruby class inheritance. Given the following simple example:
class A
def my_class; self.class.name end
end
class B < A
end
The generated class in B.java inherits from RubyObject rather than A, rendering the B class completely broken in Java.
On a somewhat related note, module inclusion doesn't seem to work either. A class with include M doesn't get M's methods in the generated Java code.
Am I missing something in my understanding of Ruby or JRuby?
This is still an issue indeed as the jruby compiler still produces RubyObject for the classes.
The only workaround that I know to this is to use the JRuby ScriptEngine from Java to eval your JRuby code. For example, here is some JRuby code:
require 'java'
java_import 'javax.swing.JFrame'
java_import 'javax.swing.JButton'
class MyFrame < JFrame
def initialize
super('Test')
content_pane.add(JButton.new("Hello"))
pack()
end
end
This code can then be called from a Java class like this:
import javax.swing.JFrame;
import javax.script.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
Reader reader = new FileReader("myframe.rb");
engine.eval(reader);
// Instantiate the JRuby class, and cast the result of eval.
JFrame frame = (JFrame) engine.eval("MyFrame.new");
frame.setVisible(true);
}
}
Here the object returned by eval can be casted into JFrame, just as you would expect. See also this question for that problem.

SWIG: generate additional (hand-rolled) Java class

I'm using SWIG to generate a Java JNI wrapper for my DLL.
As part of it, I want to generate a custom exception class, but I want to provide the complete Java class implementation for my exception class myself.
I can of course just put my Java class in a separate file, but is it possible to embed such a hand-rolled Java class into a SWIG script?
Unless the class is an inner class of some sort you're pretty much left with writing it as a separate file since that's what it needs to be when you come to compile the Java.
I'm slightly puzzled why you would want to write your own pure Java exception class though - the normal thing to do with SWIG would be derive from std::exception, even if it's through a %inline directive and merge the C++ exception hierarchy with the Java one naturally and for free.
There is a workaround you could use if you really want (although I personally would neverdo it) to generate a pure Java class from the SWIG interface though:
%module test
%nodefaultctor MyException;
%typemap(javabody) MyException %{
// Java stuff goes here (or in javacode typemap)
%}
%typemap(javafinalize) MyException ""
%typemap(javadestruct) MyException ""
struct MyException {};
Which generates:
public class MyException {
// stuff goes here
}
But since that is clearly an ugly hack I'd strongly recommend avoiding it entirely and just writing the class like normal in your source distribution.

Castle Windsor Typed Factory Facility equivalents

do any other .NET IoC containers provide equivalent functionality to the typed factory facility in Castle Windsor?
e.g. if I am using an abstract factory pattern in a WPF application:
public class MyViewModel
{
private IAnotherViewModelFactory factory;
public void ShowAnotherViewModel()
{
viewController.ShowView(factory.GetAnotherViewModel());
}
}
I don't want to have to create a manual implementation of IAnotherViewModelFactory for every type of ViewModel I wish to show, I want the container to take care of this for me.
AutoFac has a feature called Delegate Factories, but as far as I can tell, it works only with delegates, and not interfaces.
I haven't encountered anything similar to Castle's Typed Factory Facility in neither StructureMap nor Unity, but that doesn't necessarily mean that they're not there...
The only way I can imagine that something like this could be implemented for interfaces is via a dynamic proxy. Since Castle Windsor has a Dynamic Proxy, but few other containers have anything similar, this might go a long way to explain why this feature isn't ubiquitous.
Unity also offers interception capabilities, so it must have some sort of dynamic proxy implementation, but I'm pretty sure it doesn't have anything equivalent to Typed Factories. Compared to other containers, Unity is rather basic.
In Autofac you can implement typed factories on top of the delegate approach Mark mentions. E.g.
class AnotherViewModelFactory : IAnotherViewModelFactory {
Func<AnotherViewModel> _factory;
public AnotherViewModelFactory(Func<AnotherViewModel> factory) {
_factory = factory;
}
public AnotherViewModel GetAnotherViewModel() {
return _factory();
}
}
If this class is registered with the container, along with AnotherViewModel Autofac will provide the Func<AnotherViewModel> implementation implicitly:
builder.RegisterType<AnotherViewModel>();
builder.RegisterType<AnotherViewModelFactory>()
.As<IAnotherViewModelFactory>();
Practically any interface you can implement using Typed Factory Facility can be implemented in Autofac using this kind of approach. The primary difference is that the Windsor implementation configures the factory through the component registration API, while in Autofac the factory is a component in its own right.
For more sophisticated examples you might like to look at: http://code.google.com/p/autofac/wiki/RelationshipTypes and http://nblumhardt.com/2010/01/the-relationship-zoo/.
I have recently implemented an equivalent of Castle Windsor Typed Factories for Unity. You can find the project at https://github.com/PombeirP/Unity.TypedFactories, and the NuGet package at http://nuget.org/packages/Unity.TypedFactories.
The usage is the following:
unityContainer
.RegisterTypedFactory<IFooFactory>()
.ForConcreteType<Foo>();
The parameter matching is done by name, which is fine for my needs, although the library could easily be extended to support other needs.

Creating bean PropertyDescriptor using JRuby

I'm trying to port some java to jruby, and it uses a beans PropertyDescriptor. The original code is:
new PropertyDescriptor("splitEvaluator", CrossValidationResultProducer.class)
which I've tried to port to:
PropertyDescriptor.new("splitEvaluator", CrossValidationResultProducer)
However, I get the error:
no constructor with arguments matching [class org.jruby.RubyString, class org.jruby.RubyClass] on object #<Java::JavaBeans::PropertyDescriptor:0x86f847> (NameError)
The PropertyDescriptor API says the second argument should be a Java Class. What do I need to pass for this to work in JRuby?
I can see an argument that it's a bug that it doesn't work the way you originally expected. Or at least that JRuby would be smart enough to convert a Ruby class representation of a Java class to a Java class argument.
As it is, using #java_class works, as you found out.
I need to use the Java class, rather than the Ruby representation of the Java class. This works.
PropertyDescriptor.new("splitEvaluator", CrossValidationResultProducer.java_class)