AspectJ: #AfterReturning - aop

I've created this pointcut:
#Pointcut("execution(* com.living.commty.boot.resources.*.* (..))")
public void resourcesCut() {}
I'm trying to get the return value after having been returned:
#AfterReturning(pointcut="resourcesCut()", returning="result")
public void afterReturning(JoinPoint joinPoint, Object result)
{
//...
}
The problem is that it's cutting only 6 advises. However, if I not set returning:
#AfterReturning(pointcut="resourcesCut()")
public void afterReturning(JoinPoint joinPoint)
{
this.logAfterReturningTrace(joinPoint, null);
}
it's cutting up to 39 advises.
What am I doing wrong?
I'm trying to get all returned values of any "resourcesCut" pointcut execution methods...

Related

Not able to add the objects to redisson map of queue

I recently started exploring redisson for one of the use-case, where the map should hold string & queue of pojo objects. I tried to add the objects to queue for a particular key but when I'm retrieving it's values, it is giving empty results.
#Autowired
private RedissonClient redissonClient;
private RMapCache<String, Queue<AbstractXXXEvent>> mapCache;
#PostConstruct()
public void init() {
this.mapCache = redissonClient.getMapCache("test8", JsonJacksonCodec.INSTANCE);
}
#PreDestroy
public void cleanup() {
if (Objects.nonNull(redissonClient)) {
redissonClient.shutdown();
}
}
#RestController
class TestController {
#GetMapping("/get")
public Set<Map.Entry<String, Queue<AbstractXXXEvent>>> get() {
return mapCache.entrySet();
}
#PostMapping("/post")
public void post() {
mapCache.put("test", new ConcurrentLinkedQueue<>());
Queue<AbstractXXXEvent> queue = mapCache.get("test");
queue.add(new aXXXEvent().setDescription("compile done"));
queue.add(new bXXXEvent());
queue.add(new cXXXEvent().setDescription("completed"));
}
}
When I do a get request, it is giving the empty result with given key ex: [{"test":[]}]. Kindly provide your suggestions on how to fix this.
You need to put Redisson's RQueue instead of ConcurrentLinkedQueue

Should an API controller attempt to catch all 500 internal server errors?

I apologize if this has been asked before, please link me to it. I am having a hard time finding discussion as to whether it is an acceptable practice to catch all internal server errors (500) in an API.
I have seen some arguments for it and some against it.
I've always heard that one should send a status instead of errors when possible. However, I do see how the 500 is semantically taking responsibility for a failed request and letting a client know that their request may not be at fault. But a status can convey that as well and then the 500 is just reserved for application container level errors not errors in the database or a class library.
Is there an accepted standard or is this an opinion topic?
e.g.
public HttpResponseMessage GetUserRoles()
{
try
{
return Request.CreateResponse(HttpStatusCode.OK, AuthorizationService.GetUserRoles());
}
catch (SqlException sqle)
{
// log the exception
return Request.CreateResponse(HttpStatusCode.BadRequest, "A data error occured. Contact IT Support.");
}
catch (Exception e)
{
// log the exception
return Request.CreateResponse(HttpStatusCode.BadRequest, "An error occured. Contact IT Support.");
}
}
A good practice is to always return the same structure
public interface IResponse<T>
{
MsgType MsgType { get; }
string Msg { get; }
T Result { get; }
string Origin { get; }
}
Then you can have a MasterApiController with these methods
[NonAction]
public IHttpActionResult ResponseOk<T>(T result)
{
return Ok<IResponse>(ResponseFactory.Create<T>(result, "", "Negocio"));
}
[NonAction]
public IHttpActionResult ResponseEx(Exception ex, string msg = "Un error ha ocurrido.")
{
return ResponseMessage(Request.CreateResponse<IResponse>(HttpStatusCode.InternalServerError, ResponseFactory.Create(msg, ex, "Negocio")));
}
And in your controller that inherits from the master one you call this
[HttpGet]
[Route("Api/Alumno/Search")]
public dynamic Search(string codigo, string nombre, string estado, int? curso, int? paralelo)
{
return ResponseOk<dynamic>(result);
}
For all your non controlled exceptions you can have an action filter and manage them
public class ErrorLoggingFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
//Exception
}
}

PIG Algebraic UDF with arguments : Combiner optimizer error

I'm trying to build a Pig UDF that performs some aggregation on a variable of type double. To do so, I built an algebraic UDF called Aggreg. It is called in the following script:
REGISTER 'Test.jar';
DEFINE Aggreg com.pig.test.Agreg();
records = LOAD '/tmp/Test.csv' USING PigStorage(',') AS (v1:chararray, v2:double);
grouped_rec = GROUP records ALL;
test = FOREACH grouped_rec GENERATE Aggreg(records.v2) AS val;
DUMP test;
This works fine as it is. Then, I wanted to use the arguments for this UDF so I added a public constructor with one String argument.
I just changed the DEFINE statement in the previous script but haven't yet used the argument in the UDF Java code:
DEFINE Aggreg com.pig.test.Agreg('Test');
And now I get the following error:
ERROR org.apache.pig.tools.grunt.Grunt - ERROR 2018: Internal error. Unable to introduce the combiner for optimization.
Any ideas where this could come from?
Using Algebraic interface, you must implement two constructors in classes Initial, Intermed and Final, the default constructor and constructor with the parameter you use.
static public class Initial extends EvalFunc<Tuple> {
public Initial(){}
public Initial(String str){Aggreg.string=trs;}
#Override
public Tuple exec(Tuple input) throws IOException {
...
}
}
static public class Intermed extends EvalFunc<Tuple> {
public Intermed(){}
public Intermed(String str){Aggreg.string=trs;}
#Override
public Tuple exec(Tuple input) throws IOException {
...
}
}
static public class Final extends EvalFunc<Tuple> {
public Final(){}
public Final(String str){Aggreg.string=trs;}
#Override
public Tuple exec(Tuple input) throws IOException {
...
}
}
public String getInitial() {
return Initial.class.getName();
}
public String getIntermed() {
return Intermed.class.getName();
}
public String getFinal() {
return Final.class.getName();
}

how to pass context arguments to advice in spring aop

I am learning spring aop now,and I have no idea to pass context arguments to the advice.
Note I mean the context arguments,not the normal arguments.
It is simple to pass the normal arguments,for example:
a join point:
public void read(String something){
}
#Aspect
public class SessionAspect {
#Pointcut("execution(* *.*(String)) &&args(something)")
public void sess() {
}
#Before("sess()")
public void checkSessionExist(String something) {
//Here
}
}
Then the something argument will be passed to the the advice checkSessionExist.
But how about I want to get the context arguments like HttpSession or something else?
a join point:
public void listUser(){
dao.list(User.class,.....);
}
#Aspect
public class SessionAspect {
#Pointcut("execution(* *.*(String))")
public void sess() {
}
#Before("sess()")
public void checkSessionExist(String something) {
//Here
}
}
In this example,the listUser join point is only allowed for logined user.
So I want to check if there is a identify in the current HttpSession,so I need to get an instance of HttpSession at the advice checkSessionExist.
But how to get it?
The simplest way is to add the HttpSession argumets to all the joit points like this:
public void listUser(HttpSession session){
dao.list(User.class,.....);
}
However this have gone against the AOP it self. In my opinion,the join point even does not need to know the exist of the Aspect,isn't it?
How to fix it ?
Instead of passing HttpSession via #Pointcuts, you could fetch HttpSession reference in the #Aspect itself
RequestContextHolder.currentRequestAttributes()
.getAttribute("user", RequestAttributes.SCOPE_SESSION)
#Aspect
public class SessionAspect {
// fetch the current HttpSession attributes and use as required
private ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
#Pointcut("execution(* *.*(String))")
public void sess() {
}
#Before("sess()")
public void checkSessionExist(String something) {
//Here
}
}

Using NHibernate and Mono.Data.SQLite

I read and implemented Trying to using Nhibernate with Mono & SQLite - can't find System.Data.SQLite
However, as the last comment there states this seems not to work with NHibernate 3.1
The error is
HibernateException: The IDbCommand and IDbConnection implementation in
the assembly Mono.Data.Sqlite could not be found. Ensure that the
assembly Mono.Data.Sqlite is [...reachable...]
I have Mono.Data.Sqlite in the GAC.
I have tried both specifying "Mono.Data.Sqlite" as well as typeof(Mono.Data.Sqlite.SqliteConnection).Assembly.FullName as the name of the assembly
Has anyone any Ideas how to get this working?
There is a problem in the answer of Trying to using Nhibernate with Mono & SQLite - can't find System.Data.SQLite .
For the given constructor (3 parameters) to work the assembly in question (Mono.Data.Sqlite) needs to be loaded first.
This works if the 4-parameter base contructor is used like this:
public class MonoSQLiteDriver : NHibernate.Driver.ReflectionBasedDriver
{
public MonoSQLiteDriver()
: base(
"Mono.Data.Sqlite",
"Mono.Data.Sqlite",
"Mono.Data.Sqlite.SqliteConnection",
"Mono.Data.Sqlite.SqliteCommand")
{
}
public override bool UseNamedPrefixInParameter {
get {
return true;
}
}
public override bool UseNamedPrefixInSql {
get {
return true;
}
}
public override string NamedPrefix {
get {
return "#";
}
}
public override bool SupportsMultipleOpenReaders {
get {
return false;
}
}
}
(Still, credit goes to http://intellect.dk/post/Why-I-love-frameworks-with-lots-of-extension-points.aspx for the original idea - thanks.)
And if you use FluentNHibernate, then you'll also need:
public class MonoSQLiteConfiguration : PersistenceConfiguration<MonoSQLiteConfiguration>
{
public static MonoSQLiteConfiguration Standard
{
get { return new MonoSQLiteConfiguration(); }
}
public MonoSQLiteConfiguration()
{
Driver<MonoSQLiteDriver>();
Dialect<SQLiteDialect>();
Raw("query.substitutions", "true=1;false=0");
}
public MonoSQLiteConfiguration InMemory()
{
Raw("connection.release_mode", "on_close");
return ConnectionString(c => c
.Is("Data Source=:memory:;Version=3;New=True;"));
}
public MonoSQLiteConfiguration UsingFile(string fileName)
{
return ConnectionString(c => c
.Is(string.Format("Data Source={0};Version=3;New=True;", fileName)));
}
public MonoSQLiteConfiguration UsingFileWithPassword(string fileName, string password)
{
return ConnectionString(c => c
.Is(string.Format("Data Source={0};Version=3;New=True;Password={1};", fileName, password)));
}
}
I have not encountered any problems so far...