classOf T instead of T$ for Java library that does reflection - java

I'm using Scala with a Java library that expects to be passed a class with a public static void main(java.lang.String[]) so it can run call it via reflection for integration tests.
object RestServer {
def main(args: Array[String]): Unit = { /* run the server */ }
}
Due to the behavior described in this answer to another question, this gets compiled to two classes.
public final class com.example.RestServer$ {
public static final com.example.RestServer$ MODULE$;
public static {};
public void main(java.lang.String[]);
}
and
public final class com.example.RestServer {
public static void main(java.lang.String[]);
}
When I pass the class to the library
#IntegrationTest(main = classOf[RestServer.type])
class MyTests extends RapidoidIntegrationTest { }
I'm actually passing the object singleton instance (RestServer$), not the RestServer class that has the static void main() method.
This wouldn't be a problem, except the library verifies that the method it is calling is both public and static before calling it?
How can I get the RestServer class instead?

If you have control over the RestServer source file you can add an empty companion class.
object RestServer {
def main(args: Array[String]): Unit = { /* run the server */ }
}
class RestServer
That way Scala will recognize that a class RestServer exists, so classOf[RestServer] will compile and give you the class that contains the static method.

Related

MockitoException when trying to mock java.lang.System

I have a test case that mock a static method of java.lang.System class:
#Test
fun `getLocalTime()`() {
// Arrange
val staticMock = Mockito.mockStatic(System::class.java)
Mockito.`when`(System.currentTimeMillis()).thenReturn(1000L)
// Action
val res = deviceTimeProvider.getLocalTime()
// Assert
Truth.assertThat(res).isEqualTo(1000L)
staticMock.close()
}
But when I run the test, I got this error:
org.mockito.exceptions.base.MockitoException: It is not possible to
mock static methods of java.lang.System to avoid interfering with
class loading what leads to infinite loops
Why does this happen? How can I mock methods of java.lang.System class?
While Mockito since 3.4.0 version allows mocking static methods it is not allowed to mock the Thread and System static methods, see this comment on github
Finally note that Mockito forbids mocking the static methods of System (and Thread). Those methods are to much cemented into class loading which happens in the same thread. At some point, we might add instrumentation to class loading to temporarily disable the static mocks within it to make mocking these classes, too, where we also would need to disable their intensification properties. You can however easily mock Instant.now().
If you like ugly solutions you can still mock System with PowerMockito
#PrepareForTest(System.class)
public class TestCase {
#BeforeClass
public void setup() {
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.currentTimeMillis()).thenReturn(1000L);
}
...
But I would avoid mocking System classes if possible. You can still wrap it in method and mock this method.
To mock the static methods of java.lang.System class with the help of Mockito.
Create an interface i.e ISystem.java
public interface ISystem {
String getProperty(String name);
Long getCurrentTimeInMillis();
}
2- Create the implementation class of ISystem interface i.e ISystemImpl.java
public class ISystemImpl implements ISystem {
#Override
public String getProperty(final String name) {
return System.getProperty(name);
}
#Override
public Long getCurrentTimeInMillis() {
return System.currentTimeMillis();
}
}
3- Use Isystem.java inside your DeviceTimeProvider.java class.
public class DeviceTimeProvider {
#NonNull private final ISystem mISystem;
public DeviceTimeProvider(ISystem iSystem){
mIsystem = iSystem;
}
public Long getLocalTime(){
return mIsystem.getCurrentTimeInMillis()
}
}
4- Now finally mock the ISystem interface inside your test class.
public class DeviceTimeProviderTest {
private ISystem mISystem;
private DeviceTimeProvider sut;
#Before
public setup(){
mIsystem = mockito.mock(ISystem.class)
sut = new DeviceTimeProvider(mISystem);
}
#Test
public void getDeviceLocalTime(){
Long expectedTime = 1000L;
mockit.when(mISystem.getCurrentTimeInMillis()).thenReturn(expectedTime);
Long actualTime = sut.getLocalTime();
Assert.assertEquals(actualTime, expectedTime);
}
}
OUTPUT

Override Java methods in Python using Pyjnius

I would like to use Pyjnius to create a Python class that extends a Java class and overrides some of its methods.
Specifically, these Java classes:
public class A {
public void test_method() {
System.out.println("In parent test_method!!!");
}
public static void run(A a) {
System.out.println("Running...");
a.test_method();
}
}
and
public class B extends A {
public void test_method() {
System.out.println("test method");
}
public static void main(String[] args) {
A.run(new B());
}
}
When I run that I see:
Running...
test method
How do I re-implement B in Python using Pyjnius?
This is my attempt:
import jnius_config
jnius_config.set_classpath('jars/testClasses.jar')
from jnius import autoclass, PythonJavaClass, JavaClass, MetaJavaClass, java_method
A = autoclass('test.pyjnius.A')
class B(A):
__javaclass__ = 'test/pyjnius/A'
#java_method('()Z')
def test_method(self):
print("test method")
A.run(B())
When I run the Python version I see this:
Running...
In parent test_method!!!
It isn't properly overriding test_method. How do I fix that?
The answer here is that what I am trying to do is not possible. The JVM cannot call the a method implemented in a Python subclass because it doesn't even know it exists.
The workaround is to implement the run method in class B, but make accommodations for the subclass's method. Something like this:
class B(A):
__javaclass__ = 'test/pyjnius/A'
#java_method('()Z')
def test_method(self):
print("test method")
def run(self):
A.runPart1(self)
self.test_method()
A.runPart2(self)
With runPart1 and runPart2 implemented in Java in a modified version of class A.

Static function not visible in kotlin when extended from java

I'm writing Kotlin alongside java in an Android project, I have an abstract Java BaseApplication class which has some static methods, and my Application classes for each flavors extends this BaseApplication class (called App.kt) and are written in Kotlin. I wonder why I cant access BaseApplication static functions through App class in Kotlin code
public abstract class BaseApplication extends Application {
public static void staticFunction(){
Log.d("TAG", "some log...");
}
}
public class App : BaseApplication() {
fun doSomething(){
Log.w("TAG", "doing something")
}
I can call App.staticFunction() from a Java class but I cant call it from a Kotlin class. Am I doing something wrong? Why I can't call App.staticFunction() ? What is the difference?
I can do this from java:
public class JavaTest {
public void main(String[] args) {
App.staticFunction();
}
}
But this(kotlin) gives me compile error:
class KotlinTest {
fun main(args: Array<String>) {
App.staticFunction() //unresolved reference: static function
}
}
(I know I can access staticFunction through AbstractApplication, I just want to know why I cant access it through App class?)
From the Kotlin documentation on Java interop:
Static members of Java classes form "companion objects" for these
classes. We cannot pass such a "companion object" around as a value,
but can access the members explicitly ...
Your App class is a Kotlin class and doesn't know anything about the static method. However there should be a companion object that has been created for the static Method on the BaseApplication Java class. So you should be able to call the static method with
BaseApplication.staticFunction()
you can use easily
public class App : BaseApplication() {
fun doSomething(){
Log.w("TAG", "doing something")
BaseApplication.staticFunction()
}
override fun onCreate() {
super.onCreate()
staticFunction() // you can call without problem
}
}

Extending the main class in Java

I need to extend the functionality of my main class, by overriding some of its methods. I was expecting that the class extending the main class would be able to be run. However, Eclipse doesn't recognize MyLauncher as a runnable class. In the following code, I have a setup() method that is overridden by the subclass. What I want is a way to run the main(..) from the super class but also the setup from the subclass.
// Launcher.java
public class Launcher {
Launcher instance;
public static void main (args[]) {
instance = new Launcher(); // This is likely the problem
instance.setup();
}
public void setup() {
System.out.println("Default agent setup.");
}
}
// MyLauncher.java
public class MyLauncher extends Launcher {
public void setup() {
System.out.println("New agent setup!");
}
}
I accept alternatives to this. I can't add a main method to the subclass, though. The Launcher class is inside an API i'm making, so it can't refer to the class MyLauncher that is using the API.
edit: I think this is to specific to my problem. I decided to search for a new approach. Since I'm working with JDT, I'm going to parse the Launcher and inject the class.
Static methods are not inherited, they're always bound to the class that defines them, and need to be called explicitely.
In you case, the MyLauncher needs a main() method too, and could then delegate to the main() method of Launcher:
public class MyLauncher extends Launcher {
public static void main (String[] args) {
Launcher.main(args);
}
protected void setup() {
System.out.println("New agent setup!");
}
}
Protected methods can not be called from outside. So the MyLauncher.setup() do not override Launcher.setup() and instance.setup(); calls the public method from Class Launcher.
There can only be one main method in your project, that is one entry point to the program. So let's assume you're going to be keeping the main method in the Launcher class.
Your main method signature should be:
public static void main (String args[])
And unless you want the setup() method from the launcher to be called you'd want to do:
instance = new MyLauncher();
That would call the setup() method from MyLauncher.
If you want to call setup() from the Launcher class you need to instantiate the launcher class:
instance = new Launcher();
If you want to be able to run MyLauncher.setup(), the variable must be a MyLauncher. You are initializing and storing a Launcher in the main() function.
If the two classes are in the same package, or Launcher.java imports the MyLauncher class, then the main() function in Launcher should be able to be:
public class Launcher {
Launcher instance;
public static void main(String[] args) {
instance = new MyLauncher();
if(instance instanceof MyLauncher) {
((MyLauncher) instance).setup();
} else
{
instance.setup();
}
}
}
As you say, the fact that you create an instance of Launcher directly in main means that no inheritance is available. Even if you could start MyLauncher easily from Eclipse, within the main method you wouldn't know which type had actually been used to start it. I can't see any easy solution that doesn't involve either creating a main method in each class or providing the class name as a command-line argument. I would probably separate the "running" from anything else:
public class Launcher {
public static void launch(LaunchConfiguration configuration) {
configuration.setup();
...
}
}
public class LaunchConfiguration {
public static void main(String[] args) {
Launcher.launch(new LaunchConfiguration());
}
public void setup() {
}
}
public class MyLaunchConfiguration {
public static void main(String[] args) {
Launcher.launch(new MyLaunchConfiguration());
}
#Override
public void setup() {
}
}

How to call main method of a Scala program from the main method of a java program?

Suppose I have a Scala class and a Java class in a Java project and the scala class is like below
class Sam {
def main(args: Array[String]): Unit = {
println("Hello")
}
}
How can I call it's main method from the main method of a java program which is present in the same project
Typically, main methods are static in Java, and in an object in Scala. This allows you to run them from the command line. Your code defines a class, not an object.
I'd suggest changing your Scala code to:
object Sam {
def main(args: Array[String]): Unit = {
println("Hello")
}
}
You can then call this from your Java main method as follows:
class Foo {
public static void main(String[] args) {
Sam.main(args);
}
}

Categories