Quarkus security smallrye jwt - security

I'm making a webservice in quarkus, and I want to generate tokens validate the user in my endpoints (the users are located in a JDBC). I will not use other services like keycloak. Just quarkus and my front (vuejs).
I'm trying to generate the tokens just in quarkus. How can I do it?
I'm doing something like this...
`#ApplicationScoped
public class JwtGen {
public void gen() {
String token =
Jwt.upn("arthur")
.groups(new HashSet<>(Arrays.asList("User")))
.sign();
System.out.println(token);
}
}
`
I created a publicKey.pem and in application.propperties, make this linemp.jwt.verify.publickey.location=publicKey.pem
Edit: My application.properties
quarkus.http.cors=true
quarkus.http.cors.origins=*
quarkus.smallrye-jwt.enabled=true
mp.jwt.verify.publickey=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEqFyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwRTYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5eUF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYnsIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9xnQIDAQAB
mp.jwt.decrypt.key.location=privateKey.pem
mp.jwt.verify.issuer=https://example.com/issuer
This is the log error
io.smallrye.jwt.build.JwtSignatureException: SRJWT05009:
at io.smallrye.jwt.build.impl.JwtSignatureImpl.sign(JwtSignatureImpl.java:77)
at br.com.infralog.JwtGen.gen(JwtGen.java:17)
at br.com.infralog.JwtGen_Subclass.gen$$superforward1(JwtGen_Subclass.zig:89)
at br.com.infralog.JwtGen_Subclass$$function$$6.apply(JwtGen_Subclass$$function$$6.zig:24)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:54)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.proceed(InvocationInterceptor.java:62)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.monitor(InvocationInterceptor.java:49)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor_Bean.intercept(InvocationInterceptor_Bean.zig:521)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:41)
at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
at br.com.infralog.JwtGen_Subclass.gen(JwtGen_Subclass.zig:145)
at br.com.infralog.JwtGen_ClientProxy.gen(JwtGen_ClientProxy.zig:126)
at br.com.infralog.webservice.StateWsResource.list(StateWsResource.java:58)
at br.com.infralog.webservice.StateWsResource_Subclass.list$$superforward1(StateWsResource_Subclass.zig:324)
at br.com.infralog.webservice.StateWsResource_Subclass$$function$$27.apply(StateWsResource_Subclass$$function$$27.zig:53)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:54)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.proceed(InvocationInterceptor.java:62)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor.monitor(InvocationInterceptor.java:49)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor_Bean.intercept(InvocationInterceptor_Bean.zig:521)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:41)
at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
at br.com.infralog.webservice.StateWsResource_Subclass.list(StateWsResource_Subclass.zig:556)
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.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:408)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:69)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:138)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler$1.run(VertxRequestHandler.java:93)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:481)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2442)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1476)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.IllegalArgumentException: SRJWT05021: Please set a 'smallrye.jwt.sign.key.location' property
at io.smallrye.jwt.build.impl.JwtSignatureImpl.getKeyLocationFromConfig(JwtSignatureImpl.java:187)
at io.smallrye.jwt.build.impl.JwtSignatureImpl.sign(JwtSignatureImpl.java:72)
... 53 more
Please I'm in this for almost a weak... PLEASE HELPPP!!

I think that the answer is in the Exception message:
Please set a 'smallrye.jwt.sign.key.location' property
So if you did not yet set the private key in your application.properties this will most probably help you. Without it, it is impossible to generate a token.
This can be found in the documentation as well:
Note for this code to work we need the content of the RSA private key that corresponds to the public key we have in the TokenSecuredResource application.
How to configure and generate public and private keys is also described there.

Related

Quarkus unable to load the cassandra custom retry policy class

I am working on a task to migrate Quarkus from 1.x to 2.x and Quarkus integration with embedded Cassandra failed in unit testing with error -
Caused by: java.lang.IllegalArgumentException: Can't find class com.mind.common.connectors.cassandra.CassandraCustomRetryPolicy
(specified by advanced.retry-policy.class)
**Custom retry policy**
public class CassandraCustomRetryPolicy implements RetryPolicy {
public CassandraCustomRetryPolicy(DriverContext context, String profileName) {
}
//override methods
}
****quarkus test be like** -**
#QuarkusTest
#QuarkusTestResource(CassandraTestResource.class)
class Test {}
**CassandraTestResource class start the embedded cassandra**
public class CassandraTestResource implements QuarkusTestResourceLifecycleManager {
private Cassandra cassandra;
#Override
public Map<String, String> start() {
cassandra = new CassandraBuilder().version("3.11.9")
.addEnvironmentVariable("JAVA_HOME", getJavaHome())
.addJvmOptions("-Xms512M -Xmx512m").build();
cassandra.start();
}
I have override the default Cassandra driver policy in application.conf inside resource folder.
datastax-java-driver {
basic.request {
timeout = ****
consistency = ***
serial-consistency = ***
}
advanced.retry-policy {
class = com.mind.common.connectors.cassandra.CassandraCustomRetryPolicy
}
I have observed that my custom retry policy class comes under banned resource in QuarkusClassLoader.java-
String resourceName = sanitizeName(name).replace('.', '/') + ".class";
boolean parentFirst = parentFirst(resourceName, state);
if (state.bannedResources.contains(resourceName)) {
throw new ClassNotFoundException(name);
}
I have captured the following logs -
java.lang.ClassNotFoundException: com.mind.common.connectors.cassandra.CassandraCustomRetryPolicy
at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:438)
at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:414)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:315)
at com.datastax.oss.driver.internal.core.util.Reflection.loadClass(Reflection.java:57)
at com.datastax.oss.driver.internal.core.util.Reflection.resolveClass(Reflection.java:288)
at com.datastax.oss.driver.internal.core.util.Reflection.buildFromConfig(Reflection.java:235)
at com.datastax.oss.driver.internal.core.util.Reflection.buildFromConfigProfiles(Reflection.java:194)
at com.datastax.oss.driver.internal.core.context.DefaultDriverContext.buildRetryPolicies(DefaultDriverContext.java:359)
at com.datastax.oss.driver.internal.core.util.concurrent.LazyReference.get(LazyReference.java:55)
at com.datastax.oss.driver.internal.core.context.DefaultDriverContext.getRetryPolicies(DefaultDriverContext.java:761)
at com.datastax.oss.driver.internal.core.session.DefaultSession$SingleThreaded.init(DefaultSession.java:339)
at com.datastax.oss.driver.internal.core.session.DefaultSession$SingleThreaded.access$1100(DefaultSession.java:300)
at com.datastax.oss.driver.internal.core.session.DefaultSession.lambda$init$0(DefaultSession.java:146)
at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:98)
at io.netty.util.concurrent.PromiseTask.run(PromiseTask.java:106)
at io.netty.channel.DefaultEventLoop.run(DefaultEventLoop.java:54)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
I am using quarkus version 2.7.2.Final with cassandra driver version 4.14.0
It's not a complete answer but I wanted to leave some notes here in case anybody else can get this over the finish line before I get back to it.
The underlying problem here is that in the Quarkus test case described above the Java driver code is loaded by the QuarkusClassLoader which (a) is more restrictive about where it loads code from and (b) doesn't appear to immediately support calling it's parent if necessary. So in this case executing the following in the test will fail with a ClassNotFoundException:
CqlSession.class.getClassLoader().forName(customretrypolicyclassname)
while the following works without issue:
CqlSession.class.getClassLoader().getParent().forName(customretrypolicyclassname)
The class loader used to load CqlSession is the QuarkusClassLoader instance while it's parent is a stock JVM class loader.
The Java driver uses Class.forName() to load the classes specified for this policy. But since the Quarkus class loader is used to load the driver code itself that's the loader that's used for these reflection ops... and as mentioned above that driver has some specific characteristics that make loading external code harder.
It worked after I initialized CQL session like -
CqlSession.builder()
.addContactPoint(new InetSocketAddress(settings.getAddress(), settings.getPort()))
.withLocalDatacenter("***")
. withClassLoader(Thread.currentThread().getContextClassLoader()).build())

Jmeter Groovy reports NoSuchMethodError: ResourceOwnerPasswordCredentialsGrant when using MSAL4J

I am trying to recreate a user authentication with username and password with Microsoft Authentication Library for Java because we need to grant admin consent to a new application in a lot of tenants.
To do this, I have added a JSR233 sampler with Groovy 2.4.16 so I can create a script to use msal4j. The script looks like this:
import com.microsoft.aad.msal4j.*;
import com.nimbusds.oauth2.sdk.*;
//import java.util.concurrent.*;
Set<String> scope = Collections.singleton(Arrays.asList("openid","profile","email", "offline_access"));
String username = vars.get("USER");
String password = vars.get("PASSWORD");
//log.info("USER: " + username);
//log.info("PASSWORD: " + password);
log.info("SCOPE: " + scope);
log.info("CLIENT: " + vars.get("CLIENT"));
UserNamePasswordParameters parameters =
UserNamePasswordParameters
.builder(scope, username, password.toCharArray())
.build();
PublicClientApplication pca =
PublicClientApplication.builder(vars.get("CLIENT"))
.authority("https://login.microsoftonline.com/" + vars.get("TENANT"))
.build();
IAuthenticationResult result = pca.acquireToken(parameters).join();
When testing the sampler, however, I recieve the following error:
ERROR o.a.j.JMeter: Uncaught exception in thread Thread[Thread Group 1-1,6,main]
java.lang.NoSuchMethodError: com.nimbusds.oauth2.sdk.ResourceOwnerPasswordCredentialsGrant.<init>(Ljava/lang/String;Lcom/nimbusds/oauth2/sdk/auth/Secret;)V
at com.microsoft.aad.msal4j.UserNamePasswordRequest.createAuthenticationGrant(UserNamePasswordRequest.java:22) ~[msal4j-1.8.0.jar:1.8.0]
at com.microsoft.aad.msal4j.UserNamePasswordRequest.<init>(UserNamePasswordRequest.java:14) ~[msal4j-1.8.0.jar:1.8.0]
at com.microsoft.aad.msal4j.PublicClientApplication.acquireToken(PublicClientApplication.java:35) ~[msal4j-1.8.0.jar:1.8.0]
at com.microsoft.aad.msal4j.IPublicClientApplication$acquireToken.call(Unknown Source) ~[?:?]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) ~[groovy-all-2.4.16.jar:2.4.16]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116) ~[groovy-all-2.4.16.jar:2.4.16]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:128) ~[groovy-all-2.4.16.jar:2.4.16]
at Script29.run(Script29.groovy:24) ~[?:?]
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:321) ~[groovy-all-2.4.16.jar:2.4.16]
at org.codehaus.groovy.jsr223.GroovyCompiledScript.eval(GroovyCompiledScript.java:72) ~[groovy-all-2.4.16.jar:2.4.16]
at javax.script.CompiledScript.eval(Unknown Source) ~[?:1.8.0_271]
at org.apache.jmeter.util.JSR223TestElement.processFileOrScript(JSR223TestElement.java:223) ~[ApacheJMeter_core.jar:5.2.1]
at org.apache.jmeter.protocol.java.sampler.JSR223Sampler.sample(JSR223Sampler.java:71) ~[ApacheJMeter_java.jar:5.2.1]
at org.apache.jmeter.threads.JMeterThread.doSampling(JMeterThread.java:627) ~[ApacheJMeter_core.jar:?]
at org.apache.jmeter.threads.JMeterThread.executeSamplePackage(JMeterThread.java:551) ~[ApacheJMeter_core.jar:?]
at org.apache.jmeter.threads.JMeterThread.processSampler(JMeterThread.java:490) ~[ApacheJMeter_core.jar:?]
at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:257) ~[ApacheJMeter_core.jar:?]
at java.lang.Thread.run(Unknown Source) [?:1.8.0_271]
I think the problem may lay in the definition of scope: Set<String> scope = Collections.singleton(Arrays.asList("openid","profile","email", "offline_access")); but I am not completely sure.
Looking into the JavaDoc for the class where you getting the error I can see that it takes 2 strings as the parameters:
ResourceOwnerPasswordCredentialsGrant​(String username, Secret password)
Creates a new resource owner password credentials grant.
so most probably you're suffering from a form of a Jar Hell so double check your dependency libraries versions as if there will be mismatch it will result into API conflicts and errors like you're facing.
Also be aware that according to JMeter Best Practices you should always be using the latest version of JMeter so consider upgrading to JMeter 5.3 (or whatever is the latest version available at JMeter Downloads page) on next available opportunity

Facebook Audience Network Mediation via MoPub (Banner and Interstitial Ads)

I'm trying to mediate Facebook Audience Network via MoPub but I don't have any native ads setup. I only want to mediate banner and interstitial ads. In the MoPub documentation there's no instruction for banner and interstitial ads, only native and native banner ads.
So, I went ahead and simply added:
implementation 'com.mopub.mediation:facebookaudiencenetwork:5.5.0.8'
implementation 'com.android.support:support-annotations:28.0.0'
implementation 'com.facebook.android:audience-network-sdk:5.6.0'
to my app: build.gradle
then I initialized the Audience Network SDK inside onCreate method.
AudienceNetworkAds.initialize(this);
Then I created a HashMap:
Map<String, String> facebookConfig = new HashMap<>();
facebookConfig.put("banner", "");
facebookConfig.put("interstitial", "”);
and passed the hashmap to sdkconfiguration mediation settings:
SdkConfiguration sdkConfiguration = new SdkConfiguration.Builder("AD_UNIT_ID");
sdkConfiguration.withMediatedNetworkConfiguration(FacebookAdapterConfiguration.class.getName(), facebookConfig);
sdkConfiguration.withLegitimateInterestAllowed(false).build();
What am I missing here?
Here's the error I'm getting in Studio:
E/ActivityThread: Activity in.techpop.squarifymyphotos.MainActivity has leaked IntentReceiver com.mopub.mobileads.MoPubView$1#8492337 that was originally registered here. Are you missing a call to unregisterReceiver()?
android.app.IntentReceiverLeaked: Activity in.techpop.squarifymyphotos.MainActivity has leaked IntentReceiver com.mopub.mobileads.MoPubView$1#8492337 that was originally registered here. Are you missing a call to unregisterReceiver()?
at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:1588)
at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:1368)
at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1515)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1488)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1476)
at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:627)
at com.mopub.mobileads.MoPubView.registerScreenStateBroadcastReceiver(MoPubView.java:193)
at com.mopub.mobileads.MoPubView.<init>(MoPubView.java:155)
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at android.view.LayoutInflater.createView(LayoutInflater.java:854)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1006)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:961)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1123)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084)
at android.view.LayoutInflater.inflate(LayoutInflater.java:682)
at android.view.LayoutInflater.inflate(LayoutInflater.java:534)
at android.view.LayoutInflater.inflate(LayoutInflater.java:481)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:555)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:161)
at in.techpop.squarifymyphotos.MainActivity.onCreate(MainActivity.java:31)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
The exception your getting is just from the MoPubView or MoPubInterstitial not calling #destroy in actvities onDestroy() method.
#Override
protected void onDestroy() {
super.onDestroy();
moPubView.destroy(); }
moPubInterstitial.destroy();
}

How to fix `UnfinishedStubbingException`?

I have the following:
public class EnvWebEndpointExtensionEnvironmentPostProcessorTests {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Rule
public MockitoRule rule = MockitoJUnit.rule();
final EnvWebEndpointExtensionEnvironmentPostProcessor postProcessor = new EnvWebEndpointExtensionEnvironmentPostProcessor();
#Mock
ConfigurableEnvironment environmentMock;
#Mock
MutablePropertySources propertySourcesMock;
#Test
public void shouldAddPropertySource() {
final MutablePropertySources propertySources = new MutablePropertySources();
doReturn(propertySources) // line 40
.when(environmentMock).getPropertySources();
postProcessor.postProcessEnvironment(environmentMock, null);
assertNotNull(propertySources.get("actuators-defaults"));
}
#Test
public void shouldThrowExceptionOnFailingToAddLaptopPropertySource() {
thrown.expect(RuntimeException.class);
final MutablePropertySources propertySourcesReal = new MutablePropertySources();
doReturn(propertySourcesReal)
.when(environmentMock).getPropertySources();
doReturn(true)
.when(environmentMock).acceptsProfiles("laptop");
doReturn(propertySourcesMock)
.when(environmentMock).getPropertySources();
doThrow(IOException.class) // line 61
.when(propertySourcesMock).addBefore("actuators-defaults", any(ResourcePropertySource.class));
postProcessor.postProcessEnvironment(environmentMock, null);
}
}
When the tests are run individually, they pass but when they're both run, shouldAddPropertySource fails with:
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at com.netflix.springboot.actuators.EnvWebEndpointExtensionEnvironmentPostProcessorTests.shouldThrowExceptionOnFailingToAddLaptopPropertySource(EnvWebEndpointExtensionEnvironmentPostProcessorTests.java:61)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, which is not supported
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed
at com.netflix.springboot.actuators.EnvWebEndpointExtensionEnvironmentPostProcessorTests.shouldAddPropertySource(EnvWebEndpointExtensionEnvironmentPostProcessorTests.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.mockito.internal.junit.JUnitRule$1.evaluateSafely(JUnitRule.java:52)
at org.mockito.internal.junit.JUnitRule$1.evaluate(JUnitRule.java:43)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Considering the information I've found and the behavior above, Mockito is storing some static state but the level of my understanding isn't deep enough to figure out a fix for the above. What's the right fix and, in addition, the explanation for the fix?
If you use a matcher as an argument of a stubbed method call, all arguments must be matchers. So you need to replace "actuators-defaults" by eq("actuators-defaults").
I'm not sure why that throws that exception, though.
JB Nizet correctly diagnosed the root cause in his answer: When you use matchers for one argument, you have to use matchers for all arguments.
My hunch is that Mockito is correctly throwing InvalidUseOfMatchersException, which descends from RuntimeException, so your test erroneously passes without exercising your system-under-test. This is an important reason not to catch RuntimeException indiscriminately, especially at the top of a test method. This may also be a reason to use assertThrows or a try { methodUnderTest(); fail(); } catch (YourSpecificException expected) {} idiom.
If that's the case, you're seeing that specific exception because your test runner is calling your tests in shouldThrow, shouldAdd order in the same VM and Mockito keeps its matcher state in a static ThreadLocal that may survive between tests. If that theory is correct, then the InvalidUseOfMatchersException happens before Mockito can store the expectation from line 61, leaving the stubbing on line 61 technically unfinished. Because Mockito doesn't know when one test ends and another begins, it can't reset its state, so Mockito can only detect this case the next time you interact with Mockito (on line 40).
You could improve your experience by calling Mockito.validateMockitoUsage() in an #After method (or by using MockitoRule or MockitoJUnitRunner).

Retrofit2 and baseurl in GitLap

I am trying to learn retrofit2 by showing my project's GitLab name into recyclerView . but I can not find what is exactly what to do!!!
according gitlab wiki I found private-tokens and list of projrct.
this is my baseUrl and I create a builder:
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("https://gitlab.com/api/v4/projects?private_token=xxxxxx")
.addConverterFactory(GsonConverterFactory.create());
and this is my endpoint:
#GET("/users/:{userid}/projects")
Call<List<GitLabRepo>> reposForUser(#Path("userid") int user);
my GitLabRepo pojo class:
class GitLabRepo {
private String name;
public String getName() {
return name;
}
}
after running I got this error:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sayres.createandroidclient/com.example.sayres.createandroidclient.MainActivity}: java.lang.IllegalArgumentException: baseUrl must end in /: https://gitlab.com/api/v4/projects?private_token=rjezfrSUTn3fcugxLujm/
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: java.lang.IllegalArgumentException: baseUrl must end in /: https://gitlab.com/api/v4/projects?private_token=xxxxxx/
at retrofit2.Retrofit$Builder.baseUrl(Retrofit.java:513)
at retrofit2.Retrofit$Builder.baseUrl(Retrofit.java:456)
at com.example.sayres.createandroidclient.MainActivity.onCreate(MainActivity.java:34)
at android.app.Activity.performCreate(Activity.java:6679)
I know my problem is related to baseUrl but what is correct gitLab BaseUrl?
I want just show my project name into list at recycelerview list.
******************Edit******************
I use of poster :
https://gitlab.com/api/v4/projects?private_token=******/users/:******/projects
And I got :
{
"message": "401 Unauthorized"
}
I see into Status codes at gitlab wiki and wrote there:
401 Unauthorized The user is not authenticated, a valid user token is necessary.
but I have added Private Tokens .
remove the forward slash '/' from get i.e,change your code like this
#GET("users/:{userid}/projects/")
Call<List<GitLabRepo>> reposForUser(#Path("userid") int user);
and add '/' in your endpoint like this
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("https://gitlab.com/api/v4/projects?private_token=xxxxxx/")
.addConverterFactory(GsonConverterFactory.create());

Resources