Howdy. I'm trying to use AspectJ with Sonic ESB to intercept calls to the service() method of any custom ESB service. That means I don't know the type of the service class in advance; I only know that it implements interface XQServiceEx. The implemented service() method is invoked by the Sonic container every time a JMS message arrives at the service endpoint. However, the container has a somewhat complex internal structure, and I'm getting three invocations of my advice for each inbound message. (I hope my terminology isn't too far off.)
My aspect looks like this:
package com.ncr.eai.esb.aop;
import com.sonicsw.xq.XQService;
import com.sonicsw.xq.XQServiceEx;
import com.sonicsw.xq.XQServiceContext;
import com.sonicsw.xq.XQServiceException;
import com.ncr.eai.esb.*;
aspect XQServiceAspect {
final String id = "O : ";
pointcut serviceCall(XQServiceEx svc, XQServiceContext ctx) :
call(void XQService.service(XQServiceContext)) &&
target(svc) &&
target(com.sonicsw.xq.XQService) &&
// within(com.ncr..*) &&
args(ctx);
before(com.sonicsw.xq.XQServiceEx svc, XQServiceContext ctx): serviceCall(svc, ctx) {
System.out.println(id + "Entering XQServiceEx.service(): " + thisJoinPointStaticPart.getSignature() + " " + svc + " " + ctx + " " + this);
}
void around(com.sonicsw.xq.XQServiceEx svc, XQServiceContext ctx): serviceCall(svc, ctx) {
System.out.println(id + "In the around() advice before call to XQServiceEx.service(): " + thisJoinPointStaticPart.getSignature() + " " + svc + " " + ctx + " " + this);
proceed(svc, ctx);
System.out.println(id + "In the around() advice after call to XQServiceEx.service(): " + thisJoinPointStaticPart.getSignature() + " " + svc + " " + ctx + " " + this);
}
after(com.sonicsw.xq.XQServiceEx svc, XQServiceContext ctx) returning: serviceCall(svc, ctx) {
System.out.println(id + "Returned from XQServiceEx.service(): " + thisJoinPointStaticPart.getSignature() + " " + svc + " " + ctx + " " + this);
}
}
The output looks like this:
O : Entering XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain#c64bc2 com.sonicsw.xqimpl.service.XQServiceContextImpl#97e765 com.ncr.eai.esb.aop.XQServiceAspect#d8ce8f
O : In the around() advice before call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain#c64bc2 com.sonicsw.xqimpl.service.XQServiceContextImpl#97e765 com.ncr.eai.esb.aop.XQServiceAspect#d8ce8f
O : Entering XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper#195638a com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper#19c705e com.ncr.eai.esb.aop.XQServiceAspect#d8ce8f
O : In the around() advice before call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper#195638a com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper#19c705e com.ncr.eai.esb.aop.XQServiceAspect#d8ce8f
O : Entering XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.ncr.eai.esb.ServiceFromAspect#1510b03 com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper#19c705e com.ncr.eai.esb.aop.XQServiceAspect#d8ce8f
O : In the around() advice before call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.ncr.eai.esb.ServiceFromAspect#1510b03 com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper#19c705e com.ncr.eai.esb.aop.XQServiceAspect#d8ce8f
>>>> Inside of the actual service() method!
>>>> About to exit the actual service() method!
O : In the around() advice after call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.ncr.eai.esb.ServiceFromAspect#1510b03 com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper#19c705e com.ncr.eai.esb.aop.XQServiceAspect#d8ce8f
O : Returned from XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.ncr.eai.esb.ServiceFromAspect#1510b03 com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper#19c705e com.ncr.eai.esb.aop.XQServiceAspect#d8ce8f
O : In the around() advice after call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper#195638a com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper#19c705e com.ncr.eai.esb.aop.XQServiceAspect#d8ce8f
O : Returned from XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper#195638a com.sonicsw.xqimpl.service.XQServiceChain$XQServiceContextWrapper#19c705e com.ncr.eai.esb.aop.XQServiceAspect#d8ce8f
O : In the around() advice after call to XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain#c64bc2 com.sonicsw.xqimpl.service.XQServiceContextImpl#97e765 com.ncr.eai.esb.aop.XQServiceAspect#d8ce8f
O : Returned from XQServiceEx.service(): void com.sonicsw.xq.XQService.service(XQServiceContext) com.sonicsw.xqimpl.service.XQServiceChain#c64bc2 com.sonicsw.xqimpl.service.XQServiceContextImpl#97e765 com.ncr.eai.esb.aop.XQServiceAspect#d8ce8f
I know the results of my experimentation are kind of hard to read here, but each call to service() results in a sequence of three calls from com.sonicsw.xqimpl.service.XQServiceChain, com.sonicsw.xqimpl.service.XQServiceChain$XQInterceptorServiceWrapper, and com.ncr.eai.esb.ServiceFromAspect. I only want to see one call per message, meaning one call to service(). And I don't know in advance what the name of the third class will be. This test is being run with a custom service named com.ncr.eai.esb.ServiceFromAspect, but there may be dozens of other services that implement XQServiceEx, and I don't want to have to hard-code them; they need to be discovered at run-time. I tried to add the commented out within(com.ncr..*) phrase, but using that prevented the pointcut from working at all. I also tried to exclude com.sonicsw packages with things like !within(com.sonicsw..*), but that also stopped all pointcuts from working.
As far as deployment goes, I've got this aspect jarred up, and I'm doing load-time weaving by adding javaagent to the container command-line. The overall strategy is working, but I have spent longer than I want to admit trying to construct a pointcut that works as desired.
How do I get only one call per message?
Any "advice" appreciated!
Thanks,
Lee Grey, SOA Architect
NCR
It looks like a decorator pattern going on in there. All you probably need is to use cflowbelow() to avoid advising decorated calls.
pointcut serviceCall(XQServiceEx svc, XQServiceContext ctx) :
call(void XQService.service(XQServiceContext)) &&
target(svc) &&
target(com.sonicsw.xq.XQService) &&
args(ctx) &&
!cflowbelow(call(void XQService.service(XQServiceContext)));
Related
I'm trying to setup tests with Arch Unit to test my naming conventions, following the official examples.
It seems ArchUnit's naming assertions are case sensitive, which is bothering me.
I want to test that no classes in the package domain.service contains the word service.
Given a class domain.service.FileSystemService:
This test passes:
#ArchTest
val domain_service_should_not_have_names_containing_service: ArchRule =
noClasses()
.that().resideInAPackage("..domain.service..")
.should().haveSimpleNameContaining("service")
This test fails:
#ArchTest
val domain_service_should_not_have_names_containing_service: ArchRule =
noClasses()
.that().resideInAPackage("..domain.service..")
.should().haveSimpleNameContaining("Service")
Am I missing something? Is there a way to make ArchUnit's comparisons case insensitive?
If you don't want to use haveNameMatching as proposed in the comments you can also create your own ArchConditions.
public static ArchCondition<JavaClass> containName(String namePart) {
return new NameContains(namePart);
}
private static class NameContains extends ArchCondition<JavaClass> {
private String namePart;
NameContains(String namePart) {
super("contain '" + namePart + "' in the name");
this.namePart = namePart;
}
#Override
public void check(JavaClass javaClass, ConditionEvents events) {
boolean containsName = javaClass.getSimpleName().toLowerCase().contains(namePart.toLowerCase());
String message;
if (containsName) {
message = createCheckMessage(javaClass, "contains '" + namePart + "' in the name");
} else {
message = createCheckMessage(javaClass, "does not contain '" + namePart + "' in the name");
}
events.add(new SimpleConditionEvent(javaClass, containsName, message));
}
}
// taken from com.tngtech.archunit.lang.conditions.ArchConditions
public static <T extends HasDescription & HasSourceCodeLocation> String createCheckMessage(T object,
String message) {
return object.getDescription() + " " + message + " in " + object.getSourceCodeLocation();
}
You can use it like this:
rules.add(noClasses().that().resideInAPackage("..domain.service..").should(containName("Service")));
I am trying to get list of objects from api call with retrofit but i just cant find the way to do so :(
This is the function i built:
private List<Business> businesses getBusinesses()
{
List<Business> businessesList = new ArrayList<>();
Call<List<Business>> call = jsonPlaceHolderApi.getBusinesses();
call.enqueue(new Callback<List<Business>>() {
#Override
public void onResponse(Call<List<Business>> call, Response<List<Business>> response) {
if(!response.isSuccessful())
{
textViewResult.setText("Code: " + response.code());
return;
}
List<Business> businesses = response.body();
for(Business business : businesses)
{
String content = "";
content += "ID: " + business.getId() + "\n";
content += "Name: " + business.getName() + "\n";
content += "On promotion: " + business.isOnPromotion() + "\n\n";
textViewResult.append(content);
}
businessesList = businesses;
}
#Override
public void onFailure(Call<List<Business>> call, Throwable t) {
call.cancel();
textViewResult.setText(t.getMessage());
}
});
}
I am trying to get the businesses response and return it.
can anyone help me?
Feeling frustrated :(
The way your executing the Retrofit call is asynchronous - using call.enqueue. there's nothing wrong with this approach. In fact it's perhaps the best option, since network calls can take a while and you don't want to block unnecessarily.
Unfortunately, this means you cannot return the result from the function. In most scenarios, if you did, the call would likely finish after the return making your return useless.
There are several ways to deal with this, the simplest one is to use callbacks. For example:
interface OnBusinessListReceivedCallback {
void onBusinessListReceived(List<Business> list);
}
private void businesses getBusinesses(OnBusinessListReceivedCallback callback){
Call<List<Business>> call = jsonPlaceHolderApi.getBusinesses();
call.enqueue(new Callback<List<Business>>() {
#Override
public void onResponse(Call<List<Business>> call, Response<List<Business>> response) {
if(!response.isSuccessful()){
textViewResult.setText("Code: " + response.code());
return;
}
callback.onBusinessListReceived(response.body());
}
#Override
public void onFailure(Call<List<Business>> call, Throwable t) {
call.cancel();
textViewResult.setText(t.getMessage());
}
});
}
You can then call it like so:
getBusinesses(new OnBusinessListReceivedCallback() {
public void onBusinessListReceived(List<Business> list){
// list holds your data
}
});
this is my HandlerFunction
public Mono<ServerResponse> getTime(ServerRequest serverRequest) {
return time(serverRequest).onErrorReturn("some errors has happened !").flatMap(s -> {
// this didn't called
return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN).syncBody(s);
});
}
time(ServerRequest serverRequest) method is
private Mono<String> time(ServerRequest request) {
String format = DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now());
return Mono.just("time is:" + format + "," + request.queryParam("name").get());
}
when i don't using param "name",it will throw one NoSuchElementException;
But, the Mono onErrorReturn not working!
why or what do i wrong?
The onError... operators are meant to deal with error signals happening in the pipeline.
In your case, the NoSuchElementException is thrown outside of the reactive pipeline, before anything can subscribe to the returned Mono.
I think you might get the behavior you're looking for by deferring the execution like this:
private Mono<String> time(ServerRequest request) {
return Mono.defer(() -> {
String format = DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now());
Mono.just("time is:" + format + "," + request.queryParam("name").get());
});
}
Have My DatabaseHelper Class
public class DatabaseHelper : SQLiteOpenHelper
And Methods inside like
private static readonly String CREATE_USER_TABLE = "CREATE TABLE "
+ TABLE_USERS + "(" + USER_ID + " TEXT PRIMARY KEY," + USER_PASS
+ " TEXT," + USER_NAME + " TEXT," + USER_SURNAME + " TEXT,"
+ KEY_CREATED_AT + " DATETIME" + ")";
Here my DatabaseHelper class Constructure and onCreate() onUpgrade() methods
public DatabaseHelper(Context context): base(context,DATABASE_NAME,null,DATABASE_VERSION){}
public override void OnCreate (SQLiteDatabase db)
{
db.ExecSQL (CREATE_USER_TABLE);
db.ExecSQL (CREATE_RECORDS_TABLE);
db.ExecSQL (CREATE_COMPANY_TABLE);
db.ExecSQL (CREATE_COMPANY_LIST_TABLE);
db.ExecSQL (CREATE_NOTIUPLIST_TABLE);
db.ExecSQL (CREATE_NOTIFICATION_DELETE_LIST_TABLE);
db.ExecSQL (CREATE_MYNOTIFICATION_LIST_TABLE);
}
public override void OnUpgrade (SQLiteDatabase db, int oldVersion, int newVersion)
{
throw new NotImplementedException ();
}
And I call it from mainActivity
DatabaseHelper db = new DatabaseHelper (Application.Context);
Looking through Android Device Monitor data-->data-->my package name--> but dont see any created table Where I am missing to do something?
I have also added SQLite -net PCL package
You can't view your database on an actual device, unless that device is rooted. All of the examples you are seeing that are explaining how to find your database on the file system are assuming you're using an emulator.
I am overriding the generateReport() of the IReporter interface. To do some action, I need to figure out the total Passed method, Failed method, Skipped method count and total execution time of the testng suite.
I am not sure how to get those counts. Appreciate your help on this. TIA.
You can get all information through following code :
//Iterating over each suite included in the test
for (ISuite suite : suites) {
//Following code gets the suite name
String suiteName = suite.getName();
//Getting the results for the said suite
Map<String,ISuiteResult> suiteResults = suite.getResults();
for (ISuiteResult sr : suiteResults.values()) {
ITestContext tc = sr.getTestContext();
System.out.println("Passed tests for suite '" + suiteName +
"' is:" + tc.getPassedTests().getAllResults().size());
System.out.println("Failed tests for suite '" + suiteName +
"' is:" +
tc.getFailedTests().getAllResults().size());
System.out.println("Skipped tests for suite '" + suiteName +
"' is:" +
tc.getSkippedTests().getAllResults().size());
System.out.println("Total excution time for test '" + tc.getName() +
"' is:" + (tc.getEndDate().getTime()- tc.getStartDate().getTime()));
For more details,see ITestContext interface.
You can get the total passed failed and skipped tests using the ITestListener interface
public class TestStatistics implements ITestListener {
List<ITestNGMethod> passedtests = new ArrayList<ITestNGMethod>();
List<ITestNGMethod> failedtests = new ArrayList<ITestNGMethod>();
List<ITestNGMethod> skippedtests = new ArrayList<ITestNGMethod>();
#Override
//This method will automatically be called if a test runs successfully
public void onTestSuccess(ITestResult result) {
//add the passed tests to the passed list
passedtests.add(result.getMethod());
}
#Override
//This method will automatically be called if a test fails
public void onTestFailure(ITestResult result) {
//add the failed tests to the failed list
failedtests.add(result.getMethod());
}
#Override
//This method will automatically be called if a test is skipped
public void onTestSkipped(ITestResult result) {
//add the skipped tests to the skipped list
skippedtests.add(result.getMethod());
}
}
you can get the passed,failed,skipped tests count by list.size() for respective lists.
you can also get the name of the tests passed, failed, skipped from the lists
If you want to get the test execution time then you can use the below methods
#Override
//This will be called on after the test class is instantiated
public void onStart(ITestContext context) {
context.getStartDate();
}
#Override
//This will be called after the test class run
public void onFinish(ITestContext context) {
context.getEndDate();
}
If you have multiple test classes in a suite then you can add the time of all the test classes which will be your suite run time
Hope this helps you.Kindly get back if you have any queries...