Two instances of my Liferay service implementation module - liferay

I wrote a module that defines a service:
public interface TranslationService {
// a method.
}
... a module that implements the service:
#Component(
immediate = true,
configurationPid = "my.TranslationConfiguration"
)
public class TranslationServiceImpl implements TranslationService {
log.info("Constructor " + getClass().getName()
+ " " + System.identityHashCode(this));
#Activate
#Modified
protected void activate(Map<String, Object> properties) {
log.info("Configuring " + translationService.getClass().getName()
+ " " + System.identityHashCode(this));
configuration = ConfigurableUtil.createConfigurable(
TranslationConfiguration.class, properties);
}
// an implementation of the method.
}
with its service activator:
public class ServiceActivator implements BundleActivator {
private ServiceRegistration registration;
#Override
public void start(BundleContext context) throws Exception {
registration = context.registerService(TranslationService.class.getName(), new TranslationServiceImpl(), null);
}
[...]
}
... and a module that uses the service:
#Component(
immediate = true,
configurationPid = [...]
service = Portlet.class
)
public class TranslationPortlet extends MVCPortlet {
#Reference(unbind = "-")
protected void setTranslationService(TranslationService translationService) {
log.info("Using " + translationService.getClass().getName()
+ " " + System.identityHashCode(translationService));
this.translationService = translationService;
}
private TranslationService translationService;
}
Log
Log when I start (via Gogo Shell) the API and implementation modules:
Constructor my.TranslationServiceImpl 606817095
Service registered.
STARTED my.impl_1.0.0 [538]
Constructor my.TranslationServiceImpl 362465287
Configuring my.TranslationServiceImpl 362465287
Then when I start (via Gogo Shell) the using module:
STARTED my.app_1.0.0 [558]
Using my.TranslationServiceImpl 606817095
Question
Why are two instances being used?
How to make all modules use the same instance of my service implementation?
Details
Stacktraces of the two times the implementation constructor is called:
my.TranslationServiceImpl.<init>(TranslationServiceImpl.java:56)
my.ServiceActivator.start(ServiceActivator.java:24)
org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:774)
org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:1)
java.security.AccessController.doPrivileged(Native Method)
org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:767)
org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:724)
org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:951)
org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:328)
org.eclipse.osgi.container.Module.doStart(Module.java:566)
org.eclipse.osgi.container.Module.start(Module.java:434)
org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:402)
org.apache.felix.gogo.command.Basic.start(Basic.java:729)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.apache.felix.gogo.runtime.Reflective.invoke(Reflective.java:137)
Then:
my.TranslationServiceImpl.<init>(TranslationServiceImpl.java:56)
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
java.lang.reflect.Constructor.newInstance(Constructor.java:423)
java.lang.Class.newInstance(Class.java:442)
org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:236)
org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:108)
org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:906)
org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:879)
org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:748)
org.apache.felix.scr.impl.manager.AbstractComponentManager.enableInternal(AbstractComponentManager.java:674)
org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:429)
org.apache.felix.scr.impl.manager.ConfigurableComponentHolder.enableComponents(ConfigurableComponentHolder.java:657)
org.apache.felix.scr.impl.BundleComponentActivator.initialEnable(BundleComponentActivator.java:341)
org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:403)
org.apache.felix.scr.impl.Activator.access$200(Activator.java:54)
org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:278)
org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:259)
org.apache.felix.utils.extender.AbstractExtender.modifiedBundle(AbstractExtender.java:232)
org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:482)
org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:1)
org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:232)
org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:444)
org.eclipse.osgi.internal.framework.BundleContextImpl.dispatchEvent(BundleContextImpl.java:905)
org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148)
org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEventPrivileged(EquinoxEventPublisher.java:165)
org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEvent(EquinoxEventPublisher.java:75)
org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEvent(EquinoxEventPublisher.java:67)
org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor.publishModuleEvent(EquinoxContainerAdaptor.java:102)
org.eclipse.osgi.container.Module.publishEvent(Module.java:461)
org.eclipse.osgi.container.Module.start(Module.java:452)
org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:402)
org.apache.felix.gogo.command.Basic.start(Basic.java:729)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.apache.felix.gogo.runtime.Reflective.invoke(Reflective.java:137)
So its seems like I should not instantiate the implementation in the service activator? That's how it seems to be done in this tutorial though.

You are getting a second instance of the component because you are explicitly creating it, on line 24 of ServiceActivator.java. This is revealed by the first stack trace that you posted.
Simply remove that line of code, and everything will be fine.
In fact you probably don't need ServiceActivator at all. I assume that it is the BundleActivator for your bundle? You do not need to write activators when using DS, because anything you can do in an activator can be done in a DS component, and much more besides. In fact my general recommendation is to never write bundle activators.

Neil has found the answer, let me just add a few details:
As Neil said, a service activator is not needed, despite what suggests the tutorial I linked to in my question. Just delete it.
Obviously, also remove the Bundle-Activator: line from bnd.bnd otherwise you will get a Bundle-Activator not found on the bundle class path nor in imports error when deploying.
In place of the service activator, use that "DS" thing Neil talks about. It means Declarative Services, and is an OSGi technology that works with annotations. To use it, just add a service = instruction in the #Component annotation of your implementation class, with the implemented service (API)'s interface as a value. Example:
#Component(
service = TranslationService.class,
immediate = true,
configurationPid = "my.TranslationConfiguration"
)
public class TranslationServiceImpl implements TranslationService {

Related

How to test kotlin coroutines that return Exception?

i am writing unit test for some usecase, but i found that after i add withContext(IO) in my repository and than i run my unit test again, everything works fine except the test that expect to be fail and return exception, I've read several sites about testing coroutines but I found nothing to solve it, maybe I missed something? this is my repository
class HaditsRepository #Inject constructor(
private val remote: IRemoteHaditsDatasource,
#IoDispatcher private val dispatcher: CoroutineDispatcher
): IHaditsRepository {
override fun getCategories(): Flow<ResultOf<GetCategoriesResponse>> {
return flow {
emit(ResultOf.Loading())
val result = withContext(dispatcher){ remote.getCategories() }
emit(ResultOf.Success(result))
}.catch { e->
emit(ResultOf.Failure(e))
}
}
}
this is my usecase
class GetCategoriesUsecase #Inject constructor(
private val repository: IHaditsRepository
) {
operator fun invoke() = repository.getCategories()
}
and this is my unit test
#OptIn(ExperimentalCoroutinesApi::class)
class GetCategoriesUsecaseTest {
// Mock Initialize
private lateinit var openMock: AutoCloseable
// Coroutines
private val testDispatcher = StandardTestDispatcher()
// System Under Test
private lateinit var sut: GetCategoriesUsecase
// Given Conditions
private suspend fun givenFailure(){
whenever(mockDSR.getCategories()).thenThrow(dummyException)
}
// Setup
#Before
fun setup(){
openMock = MockitoAnnotations.openMocks(this)
Dispatchers.setMain(testDispatcher)
val repository = HaditsRepository(mockDSR, testDispatcher)
sut = GetCategoriesUsecase(repository)
}
#After
fun close(){
openMock.close()
Dispatchers.resetMain()
}
....
// FAIL HEREEEEE
#Test
fun `(-) Given failure - When SUT is called - Then assert result has correct Response`(){
runTest {
// Given
givenFailure()
// When
val result = sut().last() as ResultOf.Failure
// Then
Assert.assertEquals(dummyException, result.exception)
}
}
}
and this is what I got after I ran the test
expected: java.lang.RuntimeException<java.lang.RuntimeException> but was: java.lang.RuntimeException<java.lang.RuntimeException>
java.lang.AssertionError: expected: java.lang.RuntimeException<java.lang.RuntimeException> but was: java.lang.RuntimeException<java.lang.RuntimeException>
at org.junit.Assert.fail(Assert.java:89)
at org.junit.Assert.failNotEquals(Assert.java:835)
at org.junit.Assert.assertEquals(Assert.java:120)
at org.junit.Assert.assertEquals(Assert.java:146)
at id.co.haditsku.usecase.GetCategoriesUsecaseTest$(-) Given failure - When SUT is called - Then assert result has correct Response$1.invokeSuspend(GetCategoriesUsecaseTest.kt:130)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at kotlinx.coroutines.test.TestDispatcher.processEvent$kotlinx_coroutines_test(TestDispatcher.kt:28)
at kotlinx.coroutines.test.TestCoroutineScheduler.tryRunNextTaskUnless$kotlinx_coroutines_test(TestCoroutineScheduler.kt:100)
at kotlinx.coroutines.test.TestCoroutineScheduler.advanceUntilIdleOr$kotlinx_coroutines_test(TestCoroutineScheduler.kt:120)
at kotlinx.coroutines.test.TestCoroutineScheduler.advanceUntilIdle(TestCoroutineScheduler.kt:113)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTestCoroutine(TestBuilders.kt:237)
at kotlinx.coroutines.test.TestBuildersKt.runTestCoroutine(Unknown Source)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$1$1.invokeSuspend(TestBuilders.kt:167)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$1$1.invoke(TestBuilders.kt)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$1$1.invoke(TestBuilders.kt)
at kotlinx.coroutines.test.TestBuildersJvmKt$createTestResult$1.invokeSuspend(TestBuildersJvm.kt:13)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at kotlinx.coroutines.test.TestBuildersJvmKt.createTestResult(TestBuildersJvm.kt:12)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest(TestBuilders.kt:166)
at kotlinx.coroutines.test.TestBuildersKt.runTest(Unknown Source)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest(TestBuilders.kt:154)
at kotlinx.coroutines.test.TestBuildersKt.runTest(Unknown Source)
at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt.runTest$default(TestBuilders.kt:147)
at kotlinx.coroutines.test.TestBuildersKt.runTest$default(Unknown Source)
at id.co.haditsku.usecase.GetCategoriesUsecaseTest.(-) Given failure - When SUT is called - Then assert result has correct Response(GetCategoriesUsecaseTest.kt:124)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
pleaseee hellppp
There is a strange issue where equality checks of Exceptions fail across coroutine boundaries even though they should be the same. It seems to be related to Exceptions being recreated using reflection and is discussed in detail here. It is something that has been dealt with in the tests of libraries like Turbine. There they use a custom exception that avoids this problem like the following:
/**
* This type prevents coroutines from breaking referential equality by
* reflectively creating new instances.
*/
internal class CustomRuntimeException(
message: String?,
override val cause: Throwable? = null,
) : RuntimeException(message)
I've successfully used a similar approach. So this is what you'll want to use for your dummyException.

Groovy #SelfType generating error with runtime traits

If I run the code below
import groovy.transform.SelfType
interface StringProvider {
String getString()
}
class MyStringProvider implements StringProvider {
#Override
String getString() {
"MyString"
}
}
//#SelfType(StringProvider)
trait DoubleStringProvider {
String getDoubleString() {
String s = getString()
s + s
}
}
MyStringProvider provider = new MyStringProvider()
println "provider = ${provider} (${provider.class})"
def doubleProvider = provider.withTraits DoubleStringProvider
println "doubleProvider = ${doubleProvider} (${doubleProvider.class})"
println "getDoubleString() ${doubleProvider.getDoubleString()}"
it displays
provider = MyStringProvider#213860b8 (class MyStringProvider)
doubleProvider = MyStringProvider5_groovyProxy#3d36dff4 (class
MyStringProvider5_groovyProxy) getDoubleString() MyStringMyString
when I uncomment the #SelfType statement I get
provider = MyStringProvider#476a736d (class MyStringProvider)
org.codehaus.groovy.control.MultipleCompilationErrorsException:
startup failed: DoubleStringProvider$TraitAdapterwrapper: -1: class
'DoubleStringProvider$TraitAdapter' implements trait
'DoubleStringProvider' but does not implement self type interface
'StringProvider' # line -1, column -1. 1 error
at
org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:311)
at
org.codehaus.groovy.control.ProcessingUnit.completePhase(ProcessingUnit.java:149)
at
org.codehaus.groovy.control.CompilationUnit$20.call(CompilationUnit.java:938)
at
org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:965)
at
org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:601)
at
org.codehaus.groovy.runtime.ProxyGeneratorAdapter.adjustSuperClass(ProxyGeneratorAdapter.java:225)
at
org.codehaus.groovy.runtime.ProxyGeneratorAdapter.(ProxyGeneratorAdapter.java:160)
at groovy.util.ProxyGenerator.createAdapter(ProxyGenerator.java:230)
at
groovy.util.ProxyGenerator.instantiateDelegateWithBaseClass(ProxyGenerator.java:205)
at
groovy.util.ProxyGenerator.instantiateDelegateWithBaseClass(ProxyGenerator.java:189)
at
groovy.util.ProxyGenerator.instantiateDelegate(ProxyGenerator.java:181)
at
groovy.util.ProxyGenerator.instantiateDelegate(ProxyGenerator.java:177)
at
org.codehaus.groovy.runtime.DefaultGroovyMethods.withTraits(DefaultGroovyMethods.java:19602)
at org.codehaus.groovy.runtime.dgm$841.doMethodInvoke(Unknown Source)
at
org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.invoke(PogoMetaMethodSite.java:49)
at
org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:70)
at
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:127)
at ideaGroovyConsole.run(ideaGroovyConsole.groovy:25) at
groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:266)
at groovy.lang.GroovyShell.run(GroovyShell.java:376) at
groovy.lang.GroovyShell.run(GroovyShell.java:355) at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
Method) at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566) at
org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:43)
at
org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:167)
at
org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:70)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:135)
at console.run(console.groovy:11) at
groovy.ui.GroovyMain.processReader(GroovyMain.java:571) at
groovy.ui.GroovyMain.processFiles(GroovyMain.java:490) at
groovy.ui.GroovyMain.run(GroovyMain.java:334) at
groovy.ui.GroovyMain.access$1400(GroovyMain.java:69) at
groovy.ui.GroovyMain$GroovyCommand.process(GroovyMain.java:295) at
groovy.ui.GroovyMain.processArgs(GroovyMain.java:134) at
groovy.ui.GroovyMain.main(GroovyMain.java:116) at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
Method) at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566) at
org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:110)
at
org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:128)
I understand what the error is saying but how do I make it work?
def doubleProvider = (provider as StringProvider).withTraits DoubleStringProvider doesn't work but was worth a shot
As per the documentation http://docs.groovy-lang.org/next/html/gapi/groovy/transform/SelfType.html, you need to use #SelfType annotation when you want to compile the class statically. In your case you are adding the traits dynamically, so you don't have to worry about this. Moreover, (not 100% sure though) the annotation parameter requires class name not the interface name as compiler has to make sure that the given method has really been implemented!

Mockito NullPointerException while using any

I am trying to use Mockito like this :
Mockito.when(Mockito.any(ObjectMapper.class).readValue(Mockito.any(BufferedReader.class),Mockito.any(Class.class))).thenReturn(new Person("1","abc"));
This is from Jackson library .
public <T> T readValue(Reader src, Class<T> valueType)
The reason I am doing it is because the time I reach this point of the code there are a ton of objects which were created. Mocking on every step would take time.
Any reason why I am getting NPE when code reaches this mockito statement?
Stack Trace :
java.lang.NullPointerException
at com.prashant.flax.ShellTest.givenDirectoryHasFiles(ShellTest.java:139)
at com.prashant.flax.ShellTest.testExecute(ShellTest.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
As you can see it is in a given method(this method only has this piece of code) , so I can see while debugging, it reaches over there and crashes.
As Oliver mentioned in the comments, you can't apply when to happen to all objects. Mockito works via subclassing, so you have to create a mock instance using mock, spy, or a #Mock or #Spy annotation; customize the behavior; and then install the mock using dependency injection or other similar tricks.
As to why this happens, the return value for any() actually is null; matchers like any are only supposed to be used as arguments to when and verify, and Mockito can't produce a specialized instance of Class that represents "any Class", so Mockito returns a dummy value (null) and stores data on a specialized stack of argument matchers. Though Mockito has better error messages to alert you to this situation, your code NPEs before Mockito can give you a proper exception with usage examples.
For more about matcher return values and the stack, see my other SO answer on "How do Mockito matchers work?".
To extend on what #jeff-bowman said in his answer, any() returns null, so if you need something that doesn't return null, you can try this:
/**
* never returns null
*/
private inline fun <reified T> any(type: Class<T>): T = Mockito.any(type)
/**
* returns null
*/
private inline fun <reified T> any(): T = Mockito.any<T>()
For me the actual problem was that I was trying to mock a spy. When mocking a spy you have to use the doReturn or doAnswer methods. Otherwise the method of the spy will be actually called while trying to mock it and unexpected behavior can happen. E.g. when calling when with any(), any() will just return null. So it is likely that you will get an NullPointerException.
Here is a full example that demonstrates the bahavior:
package com.company;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
public class SpyTest {
public class Controller {
public String method(String arg) {
return arg.substring(0, 1);
}
}
#Test
public void withMockTest() {
Controller controllerMocked = mock(Controller.class);
when(controllerMocked.method(anyString())).thenReturn("42");
assertEquals("42", controllerMocked.method("FOO"));
}
#Test(expected = NullPointerException.class)
public void withSpyWhenThenReturnBreakingBecauseMethodToBeMockedIsActuallyBeingCalled() {
Controller controllerSpied = spy(new Controller());
when(controllerSpied.method(any())).thenReturn("42");
}
#Test
public void withSpyDoReturnWhen() {
Controller controllerSpied = spy(new Controller());
doReturn("42").when(controllerSpied).method(any());
assertEquals("42", controllerSpied.method("FOO"));
}
}

calling a method from another method is throwing java.lang.ClassFormatError: Illegal class name

Running the groovy script using the GroovyScriptEngine. Here is the groovy file created.
BasePayCalculation.groovy
return calculate()
def calculate() {
def currentPay = currentPay
currentPay = normalize(currentPay);
// Current pay cannot be zero
if (currentPay == 0) {
throw new IllegalArgumentException("Current pay is zero")
}
}
def normalize(def it) {
if (it == null)
return 0
else
return it
}
Running this from the application, getting
java.lang.ClassFormatError: Illegal class name "cds:BasePayCalculation$normalize$0" in class file cds:BasePayCalculation$normalize$0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at org.codehaus.groovy.reflection.ClassLoaderForClassArtifacts.define(ClassLoaderForClassArtifacts.java:42)
at org.codehaus.groovy.reflection.ClassLoaderForClassArtifacts$1.run(ClassLoaderForClassArtifacts.java:86)
at org.codehaus.groovy.reflection.ClassLoaderForClassArtifacts$1.run(ClassLoaderForClassArtifacts.java:84)
at java.security.AccessController.doPrivileged(Native Method)
at org.codehaus.groovy.reflection.ClassLoaderForClassArtifacts.defineClassAndGetConstructor(ClassLoaderForClassArtifacts.java:84)
at org.codehaus.groovy.runtime.callsite.CallSiteGenerator.compilePogoMethod(CallSiteGenerator.java:217)
at org.codehaus.groovy.reflection.CachedMethod.createPogoMetaMethodSite(CachedMethod.java:228)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.createCachedMethodSite(PogoMetaMethodSite.java:212)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.createPogoMetaMethodSite(PogoMetaMethodSite.java:188)
at groovy.lang.MetaClassImpl.createPogoCallCurrentSite(MetaClassImpl.java:3122)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallCurrentSite(CallSiteArray.java:108)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at cds:BasePayCalculation.calculate(cds:BasePayCalculation.groovy:20)
at cds:BasePayCalculation.run(cds:BasePayCalculation.groovy:16)
at groovy.util.GroovyScriptEngine.run(GroovyScriptEngine.java:551)
Please help me to resolve this issue.
Extra info from below:
Running from tomcat using webapplication.
Groovy 2.1.1.
Running this using code
Binding params = new Binding()
if (context != null) {
for (String key : context.keySet()) {
Object param = context.get(key);
params.setVariable(key, param);
}
}
long time = System.currentTimeMillis();
Object object = engine.run(name, params);
Java Version 1.6
tomcat version 6.0.24
Thanks in advance.
The problem is that groovy declares a class with the same name as the script that is run and therefore the script name needs to be a valid identifier from JVM perspective. In this case I presume, the problem is the ":" character.

Why does Groovy think I'm passing an instance of the class from a static method?

I'm new to Groovy, so it's likely I am doing something wrong. I had written a configuration to be taken in by ConfigSlurper. But something goes wrong when I actually try to parse it. My code is as follows:
class CharacterMap {
public static final String CHARACTER_CONFIGURATION = 'location'
static Map<String,String> characterMap = null
public static String ASCIIize(String input)
{
if (!characterMap)
{
def property = System.getProperty( CHARACTER_CONFIGURATION )
ConfigObject config = null
if( property ) {
ConfigSlurper cs = new ConfigSlurper()
File file = new File( property )
URL location = file.toURL()
config = cs.parse(location)
}
if (config)
{
characterMap = config.characters
}
else
{
getAnonymousLogger().logp WARNING, getClass().name, 'constructor',
"Server configuration groovy file not configured with system property ${CHARACTER_CONFIGURATION}"
return input
}
}
for (String key: characterMap.keySet())
{
if (input.contains(key))
{
input = input.replace(key, characterMap.get(key))
}
}
return input
}
public static void main(String[] args)
{
print ASCIIize(args[0])
}
}
When it gets to calling the parse method it complains Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: groovy.util.ConfigSlurper.parse() is applicable for argument types: (CharacterMap, java.net.URL)
As you can see, I am only passing in one argument, which was declared to be a URL. Since all the methods of the class are static and no constructor is referenced anywhere, it's kind of bizarre that an instance is being created at all, and more bizarre still that it's being passed into the parse method. I've read other people on Stack Overflow getting MissingMethodException (though usually related to closures rather than superfluous arguments), and it being blamed on Eclipse. I am running this in IntelliJ rather than Eclipse.
EDIT: In response to the comment below the groovy version is 1.8.6. Here is the stack-trace:
Exception in thread "main" groovy.lang.MissingMethodException: No
signature of method: groovy.util.ConfigSlurper.parse() is applicable
for argument types: (CharacterMap, java.net.URL) values:
[CharacterMap#34374a16, file:/C:/Program Files
(x86)/JetBrains/IntelliJ IDEA Community Edition
11.1.2/UCP/config/CharacterMap.groovy]
Possible solutions: parse(java.net.URL), parse(groovy.lang.Script,
java.net.URL), parse(groovy.lang.Script), parse(java.lang.Class),
parse(java.lang.String), parse(java.util.Properties)
at
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)
at
org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:78)
at
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:145)
at groovy.util.ConfigSlurper.parse(ConfigSlurper.groovy:148) at
groovy.util.ConfigSlurper$parse.call(Unknown Source) at
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
at ucp.cms.search.CharacterMap.ASCIIize(CharacterMap.groovy:26) at
ucp.cms.search.CharacterMap.main(CharacterMap.groovy:51) at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601) at
com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Process finished with exit code 1

Resources