doAnswer method is not calling in mockito - mockito

I am trying to mock the success block in addCallBack of ListenableFutureCallback.class .but doAnswer method is not calling in the Test class.
public void publish(String topicName,Object object) throws Exception {
ListenableFuture<SendResult> result = kafkaMessageSender.send(topicName,object);
result.addCallBack(
s -> {
System.out.println("addCallBack..");
RecordMetadata r= s.getRecordMetadata();
RecordMetadata p= s.getProducerRecord();
},
f -> {
System.out.println("failure..");
});
}
#Test
public void publishEvent()
{
KafkMessageSender kafkMessageSender=Mockito.mock(KafkMessageSender.class);
SendResult sendResult=Mockito.mock(SendResult.class);
ListenableFuture listenablFuture=Mockito.mock(ListenableFuture.class);
Mockito.when(kafkMessageSender.send(Mockito.anyString(),Mockito.any(Object.class)).thenReturn(listenablFuture);
Mockito.doAnswer(invocation -> {
System.out.println("doAnswer..");
ListenableFutureCallback<SendResult> listenableFutureCallback=invocation.getArgument(0,ListenableFutureCallback.class);
listenableFutureCallback.onSuccess(sendResult);
return null;
}).when(listenablFuture).addCallBack(Mockito.any(ListenableFutureCallback.class));
publisher.publish("sampletopic","test");
}

Related

Routing to error channel but getting "Dispatcher has no subscribers for channel"

I have to alter an existing flow in Spring Integration (4.3.12, Java DSL). There is an existing SOAP call, after that I have to insert a new SOAP call (it is done) and if the existing SOAP call wasn't successful then the new SOAP call has to be skipped (it is where I have problems). In the flow below the acmePreCompEnricher is the existing call and the ifMLCallRequiredEnricher is the new one.
return flow -> flow.channel(ORCH_REQUEST_INPUT)
.<HomeRequest, HomeModel>transform(requestToModelTransformer)
...
//
.enrich(this::acmePreCompRequestEnricher)
.enrich(this::acmePreCompEnricher)
.handle(this.acmePreCompResponseValidator())
//
.enrich(this::ifMLCallRequiredEnricher)
//
.enrich(this::acmeRequestEnricher)
.enrich(this::acmeEnricher)
...
So in the acmePreCompEnricher I set the error channel that will handle the error:
ContentEnricher contentEnricher = enricherSpec
.requestPayload(Message::getPayload)
.requestChannel(acmePreCompEnrichmentInputChannel())
.replyChannel(acmePreCompEnrichmentOutputChannel())
.get();
contentEnricher.setErrorChannel(skipMLInputChannel());
#Bean(name = "skip.ml.input")
public MessageChannel skipMLInputChannel() {
return MessageChannels.direct().get();
}
In case of SOAP fault the message will go to the following flow:
#Bean
public IntegrationFlow processSkipML() {
return flow -> flow.channel("skip.ml.input")
.transform(ErrorMessage.class, (ErrorMessage m) -> {
Message originalMessage = ((MessageHandlingException)m.getPayload()).getFailedMessage();
return MessageBuilder.withPayload(originalMessage.getHeaders().get(HEADER_MODEL, HomeModel.class))
.copyHeaders(originalMessage.getHeaders())
.build();
})
.enrich(e -> e.propertyFunction("skipMLCall", m -> true))
.channel("enrich.ifMLCallNeeded.input");
}
Behind the ifMLCallRequiredEnricher the following flow can be found:
#Bean
public IntegrationFlow processIfMLCallRequiredFlow() {
return flow -> flow.channel("enrich.ifMLCallNeeded.input")
.route(ifMLCallRequired(), routeToMLGatewayOrBypassCall())
.channel("enrich.ifMLCallNeeded.output");
}
The ifMLCallRequired() checks if the skipMLCall is false (in case of error it is set to true in the flow after the error channel) and it will execute the new SOAP call otherwise it will skip it.
When there isn't SOAP fault the flow will go through fine.
However when SOAP fault is thrown (i.e. the message goes through the error channel) then I get the following exception:
2020-05-22 10:10:48,023 ERROR com.acme.webservice.OrchestrationServiceEndpoint Thread=qtp14486859-13 MDC=16d7cc4c-c9da-449b-8bfa-504e6d81185d Error
org.springframework.messaging.MessagingException: failure occurred in error-handling flow; nested exception is org.springframework.messaging.MessageDeliveryException: Dispatcher has no subscribers for channel 'enrich.ifMLCallNeeded.output'.; nested exception is org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers, failedMessage=GenericMessage [payload=uk.co.acme.payload.request._2017._06.Message#4a5e6c, headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#19d4520, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#19d4520, ws_soapAction=http://www.acme.co.uk/XRTEService/ProcessTran, id=902bd270-89d8-62e9-b00f-b69399241bd1, timestamp=1590138648017}], ...}]
at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:489)
at org.springframework.integration.gateway.MessagingGatewaySupport.sendAndReceiveMessage(MessagingGatewaySupport.java:426)
at org.springframework.integration.transformer.ContentEnricher$Gateway.sendAndReceiveMessage(ContentEnricher.java:481)
at org.springframework.integration.transformer.ContentEnricher.handleRequestMessage(ContentEnricher.java:383)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:109)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:148)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89)
So when there is not SOAP fault then everything is fine so the channel enrich.ifMLCallNeeded.output has subscribers which is the next enricher, see the following log entry:
2020-05-24 20:37:58,819 INFO org.springframework.integration.channel.DirectChannel Thread=qtp14486859-10 MDC=16d7cc4c-c9da-449b-8bfa-504e6d81185d Channel 'enrich.ifMLCallNeeded.output' has 1 subscriber(s).
However when SOAP fault arises then the channel won't have a subscriber (I cannot find any log entry). I think it is because I am trying to hijack the flow with the error channel.
But what can I do in this case?
I'd appreciate any help as I am stuck at the moment. Thank you very much!
Regards,
V.
Here is an example of how to properly handle errors on an enricher subFlow:
#SpringBootApplication
public class So61991580Application {
public static void main(String[] args) {
SpringApplication.run(So61991580Application.class, args);
}
private final AtomicBoolean which = new AtomicBoolean();
#Bean
public IntegrationFlow flow() {
return IntegrationFlows.from(() -> new Foo(this.which.getAndSet(!which.get()) ? "foo" : "qux"),
e -> e.poller(Pollers.fixedDelay(5000)))
.enrich(spec -> spec.requestChannel("soap1.input")
.errorChannel("soap1Error.input"))
.route("payload.bar", r -> r
.channelMapping("good", "soap2.input")
.channelMapping("bad", "cleanUp.input"))
.get();
}
#Bean
public IntegrationFlow soap1() {
return f -> f
.handle(Foo.class, (payload, headers) -> {
if (payload.getFoo().equals("foo")) {
throw new RuntimeException("test enrich failure");
}
payload.setBar("good");
return payload;
});
}
#Bean
public IntegrationFlow soap2() {
return f -> f
.handle(Foo.class, (payload, headers) -> {
payload.setBaz("soap2");
return payload;
})
.channel("cleanUp.input");
}
#Bean
public IntegrationFlow soap1Error() {
return f -> f.<MessagingException, Foo>transform(ex -> {
Foo foo = (Foo) ex.getFailedMessage().getPayload();
foo.setBar("bad");
return foo;
});
}
#Bean
public IntegrationFlow cleanUp() {
return f -> f.log();
}
public static class Foo {
private final String foo;
private String bar;
private String baz;
public Foo(String foo) {
this.foo = foo;
}
public String getFoo() {
return this.foo;
}
public String getBar() {
return this.bar;
}
public void setBar(String bar) {
this.bar = bar;
}
public String getBaz() {
return this.baz;
}
public void setBaz(String baz) {
this.baz = baz;
}
#Override
public String toString() {
return "Foo [foo=" + this.foo + ", bar=" + this.bar + ", baz=" + this.baz + "]";
}
}
}
GenericMessage [payload=Foo [foo=foo, bar=bad, baz=null], headers={id=e5a943c7-dcf1-47f3-436e-5d0350a1c6f5, timestamp=1590511422083}]
GenericMessage [payload=Foo [foo=qux, bar=good, baz=soap2], headers={id=a99d7ddb-2f40-f0f7-08b6-6340563e011d, timestamp=1590511427086}]
2

How update Room DB with API response if there is not data?

I am trying to update my database (room) with the response of my call api if my database table is empty and return to my recyclerview
API
#GET("user/patient/")
Flowable<ResponsePatient> getPatients(#Header("Authorization") String userToken);
FactoryData.class
public Flowable<List<Patient>> getPatientFromApi(){
String token = preferences.getValue(SDConstants.token);
return apiNetwork.getPatients(token).map(new Function<ResponsePatient, List<Patient>>() {
#Override
public List<Patient> apply(ResponsePatient responsePatient) throws Exception {
return PatientMapper.transform(responsePatient);
}
});
}
public Flowable<List<Patient>> listPatient(){
return appDataBase.patientDao().listPatient()
.switchIfEmpty(getPatientFromApi())
.doOnNext(s -> appDataBase.patientDao().saveAll(s));
}
I not sure how to do this. I appreciate any help.
Finally I can solve my problem.
public Flowable<List<Patient>> getPatient(){
return getPatientFromlocal()
.take(1)
.filter(list -> !list.isEmpty())
.switchIfEmpty(
Flowable.defer(() -> getPatientFromApi()));
}
public Flowable<List<Patient>> getPatientFromlocal(){
return appDataBase.patientDao().listPatient();
}
public Flowable<List<Patient>> getPatientFromApi(){
String token = preferences.getValue(SDConstants.token);
return apiNetwork.getPatients(token).map(new Function<ResponsePatient, List<Patient>>() {
#Override
public List<Patient> apply(ResponsePatient responsePatient) throws Exception {
return PatientMapper.transform(responsePatient);
}
}).doOnNext(new Consumer<List<Patient>>() {
#Override
public void accept(List<Patient> patients) throws Exception {
appDataBase.patientDao().saveAll(patients);
}
});
}

Transform Header and payload to Json nodes

I am trying to enrich payload with some Headers keys and convert to a json structure like that:
{
"Header": { ["key" : "value", "key2": "value"]}
"Payload": { "attribute" : "value" }
}
My gateway is configured like this:
#MessagingGateway
public static interface MailService {
#Gateway(requestChannel = "mail.input")
void sendMail(String body, #Headers Map<String,String> headers);
}
Here is my flow:
#Bean
public IntegrationFlow errorFlow(){
return IntegrationFlows.from(recoveryChannel())
.transform("payload.failedMessage")
.enrichHeaders(c -> c.header(FileHeaders.FILENAME, "emailErrors.json"))
.handle(this.fileOutboundAdapter())
.get();
}
How could I solve this issue?
Thanks.
To convert the whole message to the JSON, you should do something like this:
.handle((p, h) -> MessageBuilder.withPayload(new GenericMessage<>(p, h)))
.transform(Transformers.toJson())
The trick is like Transformers.toJson() doesn't care about headers and transforms only payload. So, we have to hack it a bit placing the whole message to the payload.
Since ServiceActivator (ground floor of the .handle()) returns message as is if the result is Message<?> , we don't have choice unless provide MessageBuilder and Transformers.toJson() will have all the info for your use-case.
#SpringBootApplication
public class So41223173Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(So41223173Application.class, args);
context.getBean("flow.input", MessageChannel.class)
.send(new ErrorMessage(new MessagingException(new GenericMessage<>(new Foo()))));
context.close();
}
#Bean
public IntegrationFlow flow() {
return f -> f.transform("payload.failedMessage")
.enrichHeaders(c -> c.header("foo", "bar"))
.transform(toMap(), "transform")
.transform(Transformers.toJson())
.handle(m -> System.out.println(m.getPayload()));
}
#Bean
public Transformer toMap() {
return new AbstractTransformer() {
#Override
protected Object doTransform(Message<?> message) throws Exception {
Map<String, Object> map = new LinkedHashMap<>();
Map<String, Object> headers = new LinkedHashMap<>(message.getHeaders());
headers.remove(MessageHeaders.ID);
headers.remove(MessageHeaders.TIMESTAMP);
map.put("headers", headers);
map.put("payload", message.getPayload());
return map;
}
};
}
public static class Foo {
String bar = "bar";
public String getBar() {
return this.bar;
}
public void setBar(String bar) {
this.bar = bar;
}
}
}
result
{"headers":{"foo":"bar"},"payload":{"bar":"bar"}}

get vs getProperty in groovy

It surprise me!
According to the document of groovy, groovy may use "getProperty" method to get the property of a object. So when I want to change the behavier of getting property on the special object, I use a category class to override the "getProperty" method. However, it does not work.
At last, I found groovy framework use the "get" method in the category class to get property, even if the object is not a map.
My question is that is it a bug or groovy just work like that.
This is the category class.
class DynaBeanExtension {
public static void setProperty(DynaBean bean, String propertyName, def newValue) {
try {
PropertyUtilsBean pu = null;
if (bean instanceof CustomWrapDynaBean) {
pu = bean.propertyUtilsBean;
}
if (pu != null) {
pu.setProperty(bean, propertyName, newValue);
} else {
PropertyUtils.setProperty(bean, propertyName, newValue);
}
} catch (IllegalArgumentException ex) {
bean.propertyMissing(propertyName, newValue);
}
}
public static def getProperty(DynaBean bean, String propertyName) {
try {
PropertyUtilsBean pu = null;
if (bean instanceof CustomWrapDynaBean) {
pu = bean.propertyUtilsBean;
}
if (pu != null) {
return pu.getProperty(bean, propertyName);
} else {
return PropertyUtils.getProperty(bean, propertyName);
}
} catch (IllegalArgumentException ex) {
return bean.propertyMissing(propertyName);
}
}
public static def get(DynaBean bean, String propertyName) {
try {
PropertyUtilsBean pu = null;
if (bean instanceof CustomWrapDynaBean) {
pu = bean.propertyUtilsBean;
}
if (pu != null) {
return pu.getProperty(bean, propertyName);
} else {
return PropertyUtils.getProperty(bean, propertyName);
}
} catch (IllegalArgumentException ex) {
return bean.propertyMissing(propertyName);
}
}
This is the test code:
public static class TestSubClass {
private final int e = 3, f = 4;
private final Map<String, Object> m = new HashMap<>();
public int getE() {
return e;
}
public int getF() {
return f;
}
public Map<String, Object> getM() {
return m;
}
#Override
public String toString() {
return "TestSubClass{" + "e=" + e + ", f=" + f + ", m=" + m + '}';
}
}
public static class TestClass {
private final int a = 1;
private final TestSubClass b = new TestSubClass();
public int getA() {
return a;
}
public TestSubClass getB() {
return b;
}
#Override
public String toString() {
return "TestClass{" + "a=" + a + ", b=" + b + '}';
}
}
Map<String, String> pMap = new HashMap<>();
pMap.put("b.e", "c");
PropertyUtilsBean pu = new PropertyUtilsBean();
pu.setResolver(new ExResolver(pMap));
TestClass testObj = new TestClass();
DynaBean bean = new CustomWrapDynaBean(testObj, pu);
int c = use(DynaBeanExtension) {
bean.c;
}
This is the code of ExResolver:
public class ExResolver implements Resolver {
private static final char NESTED = '.';
private static final char MAPPED_START = '(';
private static final char MAPPED_END = ')';
private static final char INDEXED_START = '[';
private static final char INDEXED_END = ']';
private final Resolver resolver;
private final Map<String, String> pMap;
public ExResolver(Map<String, String> pMap) {
this(new DefaultResolver(), pMap);
}
public ExResolver(Resolver resolver, Map<String, String> pMap) {
this.resolver = resolver;
this.pMap = new HashMap<>(pMap);
}
private String resolveExpr(String expression) {
for (Map.Entry<String, String> entry : pMap.entrySet()) {
if (expression.startsWith(entry.getValue())) {
String to = entry.getValue();
if (expression.length() == entry.getValue().length()) {
return entry.getKey();
} else {
int toTest = expression.codePointAt(to.length());
if (toTest == NESTED || toTest == MAPPED_START || toTest == INDEXED_START) {
return entry.getKey() + expression.substring(to.length(), expression.length());
} else {
return expression;
}
}
}
}
return expression;
}
#Override
public int getIndex(String expression) {
expression = resolveExpr(expression);
return resolver.getIndex(expression);
}
#Override
public String getKey(String expression) {
expression = resolveExpr(expression);
return resolver.getKey(expression);
}
#Override
public String getProperty(String expression) {
expression = resolveExpr(expression);
return resolver.getProperty(expression);
}
#Override
public boolean hasNested(String expression) {
expression = resolveExpr(expression);
return resolver.hasNested(expression);
}
#Override
public boolean isIndexed(String expression) {
expression = resolveExpr(expression);
return resolver.isIndexed(expression);
}
#Override
public boolean isMapped(String expression) {
expression = resolveExpr(expression);
return resolver.isMapped(expression);
}
#Override
public String next(String expression) {
expression = resolveExpr(expression);
return resolver.next(expression);
}
#Override
public String remove(String expression) {
expression = resolveExpr(expression);
return resolver.remove(expression);
}
}
"get" is invoked, not "getProperty"
What's more, in the real situation DynaBeanExtension is compiled with groovy. The construction of bean is compiled with java. Then by using binding, I put it into the test code which is a runtime script executed by java code.
This happens in the compilation itself. Let's look at a simpler example.
class Main {
static void main(def args) {
Foo foo = new Foo()
foo.str = ""
foo.str
}
}
For Groovy classes
class Foo {
String str
}
If you decompile the Main class, you'll see it is
public class Main implements GroovyObject {
public Main() {
Main this;
CallSite[] arrayOfCallSite = $getCallSiteArray();
MetaClass localMetaClass = $getStaticMetaClass();
this.metaClass = localMetaClass;
}
public static void main(String... args) {
CallSite[] arrayOfCallSite = $getCallSiteArray();
Foo foo = (Foo)ScriptBytecodeAdapter.castToType(arrayOfCallSite[0].callConstructor(Foo.class), Foo.class);
String str = "";
ScriptBytecodeAdapter.setGroovyObjectProperty(str, Main.class, foo, (String)"str");
arrayOfCallSite[1].callGroovyObjectGetProperty(foo);
}
}
A .[property] = call gets compiled to a ScriptBytecodeAdapter.setGroovyObjectProperty, that in turn calls the chain MetaClassImpl.setProperty > MetaMethod.doMethodInvoke > CachedMethod.invoke > java.lang.reflect.Method.invoke > [setter]
And a .[property] call gets compiled to a arrayOfCallSite[1].callGroovyObjectGetProperty, that in turn calls the chain
AbstractCallSite.callGroovyObjectGetProperty > GetEffectivePogoPropertySite.getProperty > MethodMetaProperty$GetBeanMethodMetaProperty.getProperty > MetaMethod.doMethodInvoke > CachedMethod.invoke > java.lang.reflect.Method.invoke > [getter]
For Java classes
If you use a Java version of the class being called, like this
public class Foo {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
}
The same Main decompiles to
public class Main implements GroovyObject {
public Main() {
Main this;
CallSite[] arrayOfCallSite = $getCallSiteArray();
MetaClass localMetaClass = $getStaticMetaClass();
this.metaClass = localMetaClass;
}
public static void main(String... args) {
CallSite[] arrayOfCallSite = $getCallSiteArray();
Foo foo = (Foo)ScriptBytecodeAdapter.castToType(arrayOfCallSite[0].callConstructor(Foo.class), Foo.class);
String str = "";
ScriptBytecodeAdapter.setProperty(str, null, foo, (String)"str");
arrayOfCallSite[1].callGetProperty(foo);
}
}
A .[property] = call gets compiled to a ScriptBytecodeAdapter.setProperty, that in turn calls the chain [Class].setProperty > InvokerHelper.setProperty -> MetaClassImpl.setProperty > MetaMethod.doMethodInvoke > CachedMethod.invoke > java.lang.reflect.Method.invoke > [setter]
And a .[property] call gets compiled to a arrayOfCallSite[1].callGroovyObjectGetProperty, that in turn calls the chain
AbstractCallSite.callGetProperty > GetEffectivePojoPropertySite.getProperty > MethodMetaProperty$GetBeanMethodMetaProperty.getProperty > MetaMethod.doMethodInvoke > CachedMethod.invoke > java.lang.reflect.Method.invoke > [getter]
To correct your code
As you can see from these dispatch chains, you've overridden the getter correctly (since it happens in the class itself), but if you want to override getProperty or setProperty, you have to do this in metaClass, and not the class itself. The behavior you're seeing is expected. This code demonstrates how to override each
class Foo {
String bar
}
// override using setter in category
#Category(Foo)
class FooCategory {
public String getBar() {
println "in getter"
}
public void setBar(String bar) {
println "in setter"
}
}
use (FooCategory) {
Foo foo = new Foo()
foo.bar = ""
foo.bar
}
// override using metaClass
Foo.metaClass.getProperty { String pname ->
println "in getProperty"
}
Foo.metaClass.setProperty { String pname, Object pValue ->
println "in setProperty"
}
Foo foo = new Foo()
foo.bar = ""
foo.bar
outputs
in setter
in getter
in setProperty
in getProperty
And because the getProperty/setProperty call makes the dispatch (eventually) to the getter/setter, you can prevent the getter/setter from being called at all, like this
class Foo {
String bar
}
Foo.metaClass.getProperty { String pname ->
println "in getProperty"
}
Foo.metaClass.setProperty { String pname, Object pValue ->
println "in setProperty"
}
#Category(Foo)
class FooCategory {
String getBar() {
println "in getter"
}
void setBar(String bar) {
println "in setter"
}
}
use (FooCategory) {
Foo foo = new Foo()
foo.bar = "hi foo1"
foo.bar
}
outputs
in setProperty
in getProperty

Groovy Inner Classes wont work with Apache Wicket

Im trying to write simple things with Apache Wicket (6.15.0) and Groovy (2.2.2 or 2.3.1). And Im having trouble with inner classes.
class CreatePaymentPanel extends Panel {
public CreatePaymentPanel(String id) {
super(id)
add(new PaymentSelectFragment('currentPanel').setOutputMarkupId(true))
}
public class PaymentSelectFragment extends Fragment {
public PaymentSelectFragment(String id) {
super(id, 'selectFragment', CreatePaymentPanel.this) // problem here
add(new AjaxLink('cardButton') {
#Override
void onClick(AjaxRequestTarget target) {
... CreatePaymentPanel.this // not accessible here
}
})
add(new AjaxLink('terminalButton') {
#Override
void onClick(AjaxRequestTarget target) {
... CreatePaymentPanel.this // not accessible here
}
});
}
} // end of PaymentSelectFragment class
} // end of CreatePaymentPanel class
Groovy tries to find a property "this" in CreatePaymentPanel class.. How to workaround this? It is a valid java code, but not groovy.
However,
Test.groovy:
class Test {
static void main(String[] args) {
def a = new A()
}
static class A {
A() {
def c = new C()
}
public void sayA() { println 'saying A' }
class B {
public B(A instance) {
A.this.sayA()
instance.sayA()
}
}
/**
* The problem occurs here
*/
class C extends B {
public C() {
super(A.this) // groovy tries to find property "this" in A class
sayA()
}
}
}
}
Above code wont work, the same error occurs, like in Wicket's case.
And TestJava.java, the same and working:
public class TestJava {
public static void main(String[] args) {
A a = new A();
}
static class A {
A() {
C c = new C();
}
public void sayA() {
System.out.println("saying A");
}
class B {
public B(A instance) {
instance.sayA();
}
}
/**
* This works fine
*/
class C extends B {
public C() {
super(A.this);
sayA();
}
}
}
}
What I am missing?
You can't refer to a CreatePaymentPanel.this inside of PaymentSelectFragment because there is no instance of CreatePamentPanel that would be accessible there. What would you expect that to evaluate to if it were allowed?

Resources