AOP implementation of return value decryption - aop

demand:Decryption of database query results with AOP
MybatisPlus Return results,for example:List
I customize an annotation to intercept annotated methods,
But I intercepted the method and got that the return type is List,How can I get the VO type in the list
#Component
#Aspect
#Order
public class DecryptrResultAspect {
#Pointcut("#annotation(com.sgcc.hr.recruit.graduate.common.utils.NeedDncryptResult)")
public void rsaDecodeSecurityParameterAspect() {
}
#After("rsaDecodeSecurityParameterAspect()")
public void decode(JoinPoint joinPoint) {
try {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Class returnType = signature.getReturnType();
System.out.println(returnType);
// output interface java.util.List
} catch (Exception e) {
e.printStackTrace();
}
}
}

Related

Using and extending JOOQ generated DAOs with injected DataSource?

I'm new to JOOQ... The following code seems to work in WildFly 22 but I'm not sure if that is the best way to do things. What is the preferred way to inject WF DataSource to JOOQ DAOs (my extended ones)? Is there a way to avoid doing the ".get()." in the service below and just leave #Resource(...) etc. connection related for the MyCompanyDAO to handle internally?
In other words: companyDAO.get().fetchOneById(id) vs. companyDAO.fetchOneById(id)
#Stateless
public class CompanyService extends DefaultCompanyService {
#Inject
private MyCompanyDAO companyDAO;
public Company find(Integer id) {
return companyDAO.get().fetchOneById(id);
}
}
#Stateless
public class MyCompanyDAO extends CompanyDao {
#Inject
private MyConnectionProvider cp;
public CompanyDAO get() { // since cannot use #Resource in dao constructor
this.configuration().set(cp).set(SQLDialect.POSTGRES);
return this;
}
// custom code here
}
public class CompanyDao extends DAOImpl<CompanyRecord, tables.pojos.Company, Integer> {
// jooq generated code here
}
#Stateless
#LocalBean
public class MyConnectionProvider implements ConnectionProvider {
#Resource(lookup = "java:/MyDS")
private DataSource dataSource;
#Override
public Connection acquire() throws DataAccessException {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new DataAccessException("Could not acquire connection.", e);
}
}
#Override
public void release(Connection connection) throws DataAccessException {
try {
connection.close();
} catch (SQLException e) {
throw new DataAccessException("Could not release connection.", e);
}
}
}
Put initialization logic of MyCompanyDAO inside a #PostConstruct method.
#PostConstruct
public void init() {
this.configuration().set(cp).set(SQLDialect.POSTGRES);
}
This way, you don't need to call get:
#Inject
private MyCompanyDAO companyDAO;
public Company find(Integer id) {
return companyDAO.fetchOneById(id);
}
How about using constructor injection instead? The generated DAO classes offer a constructor that accepts a Configuration precisely for that:
#Stateless
public class MyCompanyDAO extends CompanyDao {
#Inject
public MyCompanyDAO (Configuration configuration) {
super(configuration);
}
}
If for some reason you cannot inject the entire configuration (which I'd recommend), you could still inject the ConnectionProvider:
#Stateless
public class MyCompanyDAO extends CompanyDao {
#Inject
public MyCompanyDAO (MyConnectionProvider cp) {
super(DSL.using(cp, SQLDialect.POSTGRES));
}
}

Jackson Serialization Problems

I am having some trouble serializing/deserializing my classes below.
My Data class holds a list of other classes.
When I call the serialize/deserialize methods in the Data class, I get the following error:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.amazon.rancor.storage.types.ChildData: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
The error comes from the deserialize method. But I also believe the serialization is not working properly. This is what the serialized Data object looks like:
{childData:[{zipCode:{present:true},countryCode:"US"}]
The Optional field is not being serialized properly even though I have set the objectMapper.registerModule(new Jdk8Module()); field
I can't seem to figure out what I am doing wrong. Maybe I need to change something in ChildData and ChildDataV2 class. But I am not sure what.
Any pointers would be appreciated!
public class Data {
private List<ChildData> childData;
private List<ChildDataV2> childDataV2;
private static ObjectMapper objectMapper;
static {
objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.registerModule(new Jdk8Module());
}
public Data() { }
#JsonCreator
public Data(#JsonProperty("childData") final List<ChildData> childData,
#JsonProperty("childDataV2") final List<ChildDataV2> childDataV2) {
this.childData = childData;
this.childDataV2 = childDataV2;
}
public List<ChildData> getChildData() {
return childData;
}
public void setChildData(final List<ChildData> childData) {
this.childData = childData;
}
public List<ChildDataV2> getChildDataV2() {
return childDataV2;
}
public void setChildDataV2(final List<ChildDataV2> childDataV2) {
this.childDataV2 = childDataV2;
}
public String serialize() {
try {
return objectMapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
throw new RuntimeException("Failed to serialize. Data: " + this, e);
}
}
public Data deSerialize(final String data) {
try {
return objectMapper.readValue(data, Data.class);
} catch (IOException e) {
throw new RuntimeException("Failed to deserialize. Data" + data, e);
}
}
}
public class ChildData {
private final String countryCode;
private final Optional<String> zipCode;
public ChildData(final String countryCode, final Optional<String> zipCode) {
this.countryCode = countryCode;
this.zipCode = zipCode;
}
public Optional<String> getZipCode() {
return zipCode;
}
public String getCountryCode() {
return countryCode;
}
}
public class ChildDataV2 extends ChildData {
private final Object struct;
public ChildDataV2(final String cc, final Optional<String> postalCode,
final Object struct) {
super(cc, postalcode);
this.struct = struct;
}
}
The exception is quite clear right? You need to add a default constructor for ChildData or annotate the existing constructor like this:
#JsonCreator
public ChildData(#JsonProperty("countryCode") String countryCode, #JsonProperty("zipCode") Optional<String> zipCode) {
this.countryCode = countryCode;
this.zipCode = zipCode;
}

How to correctly handle errors in ASP.NET Core middleware?

I've created a HandlerMiddleware-class, which executes a handler for a specific URL.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace FailTest
{
public interface IHttpHandler
{
bool IsReusable { get; }
void ProcessRequest(HttpContext context);
}
public abstract class HandlerMiddleware<T>
where T : IHttpHandler
{
private readonly RequestDelegate _next;
public HandlerMiddleware()
{ }
public HandlerMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await SyncInvoke(context);
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.Message);
throw;
}
}
public Task SyncInvoke(HttpContext context)
{
try
{
// IHttpHandler handler = (IHttpHandler)this;
T handler = System.Activator.CreateInstance<T>();
handler.ProcessRequest(context);
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.Message);
throw;
}
return Task.CompletedTask;
}
} // End Abstract Class HandlerMiddleware
}
Now I have a class which implements a handler, e.g.
[HandlerPath("/treedata", "GET,POST")]
public class SomeFailingTask
: HandlerMiddleware<SomeFailingTask>, IHttpHandler
{
public SomeFailingTask() : this(null)
{ }
public SomeFailingTask(RequestDelegate next) : base(next)
{ }
bool IHttpHandler.IsReusable
{
get { throw new System.NotImplementedException(); }
}
void IHttpHandler.ProcessRequest(HttpContext context)
{
// Do something in DB and return result as JSON
// e.g. SQL with invalid syntax, or a missing parameter
}
}
It works fine as long as there are no errors in ProcessRequest.
But when an exception is thrown in ProcessRequest, it finishes the request with HTTP 200 OK.
What am I doing wrong ?
I get the exception, in both Invoke and SyncInvoke, but the HTTP request always finished as if everything was fine...

Retrofit Rxjava error handler

I have a service class which is used to call api requset
here is an example method:
public Observable<List<Category>> test(Location location, int radius) {
Observable<CategoryListResponse> observable = api.test();
return observable
.doOnNext(new Action1<CategoryListResponse>() {
#Override
public void call(CategoryListResponse categoryListResponse) {
//handle error
}
})
.flatMap(new Func1<CategoryListResponse, Observable<Category>>() {
#Override
public Observable<Category> call(CategoryListResponse categoryListResponse) {
return Observable.from(categoryListResponse.getCategories());
}
})
.map(new Func1<Category, Category>() {
#Override
public Category call(Category category) {
//do something...
return category;
}
})
.toList();
}
And subscribe() will be called in another class.
observable.subscribe(new Action1<List<Category>>() {
#Override
public void call(List<Category> categories) {
//on success
}
}, new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
//on error
}
});
I was thinking to do error handling in the doOnNext() before it is returned back. but how can I trigger onError()?
You should throw a runtime exception and control the exception in onError operator in case that happens
Observable<CategoryListResponse> observable = api.test();
return observable
.doOnNext(list -> {
try{
request(list);
catch(Exception e){
throw new RuntimeException(e);
}
}).onError(t->//Here you control your errors otherwise it will be passed to OnError callback in your subscriber)
.flatMap(item -> Observable.from(item.getCategories()))
.map(category-> category)
.toList();
}
Try to use lambdas, make your code much more clear and readable
You can see some RxJava examples here https://github.com/politrons/reactive

Is it possible to use one generic/abstract service in ServiceStack?

I am developing a (hopefully) RESTful API using ServiceStack.
I noticed that most of my services look the same, for example, a GET method will look something like this:
try
{
Validate();
GetData();
return Response();
}
catch (Exception)
{
//TODO: Log the exception
throw; //rethrow
}
lets say I got 20 resources, 20 request DTOs, so I got about 20 services of the same template more or less...
I tried to make a generic or abstract Service so I can create inheriting services which just implement the relevant behavior but I got stuck because the request DTOs weren't as needed for serialization.
Is there any way to do it?
EDIT:
an Example for what I'm trying to do:
public abstract class MyService<TResponse,TRequest> : Service
{
protected abstract TResponse InnerGet();
protected abstract void InnerDelete();
public TResponse Get(TRequest request)
{
//General Code Here.
TResponse response = InnerGet();
//General Code Here.
return response;
}
public void Delete(TRequest request)
{
//General Code Here.
InnerDelete();
//General Code Here.
}
}
public class AccountService : MyService<Accounts, Account>
{
protected override Accounts InnerGet()
{
throw new NotImplementedException();//Get the data from BL
}
protected override void InnerDelete()
{
throw new NotImplementedException();
}
}
To do this in the New API we've introduced the concept of a IServiceRunner that decouples the execution of your service from the implementation of it.
To add your own Service Hooks you just need to override the default Service Runner in your AppHost from its default implementation:
public virtual IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext actionContext)
{
return new ServiceRunner<TRequest>(this, actionContext); //Cached per Service Action
}
With your own:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext actionContext)
{
return new MyServiceRunner<TRequest>(this, actionContext); //Cached per Service Action
}
Where MyServiceRunner is just a custom class implementing the custom hooks you're interested in, e.g:
public class MyServiceRunner<T> : ServiceRunner<T> {
public override void OnBeforeExecute(IRequestContext requestContext, TRequest request) {
// Called just before any Action is executed
}
public override object OnAfterExecute(IRequestContext requestContext, object response) {
// Called just after any Action is executed, you can modify the response returned here as well
}
public override object HandleException(IRequestContext requestContext, TRequest request, Exception ex) {
// Called whenever an exception is thrown in your Services Action
}
}
Also for more fine-grained Error Handling options check out the Error Handling wiki page.
My solution was to add an additional layer where I can handle Logic per entity:
Base Logic Sample:
public interface IEntity
{
long Id { get; set; }
}
public interface IReadOnlyLogic<Entity> where Entity : class, IEntity
{
List<Entity> GetAll();
Entity GetById(long Id);
}
public abstract class ReadOnlyLogic<Entity> : IReadOnlyLogic<Entity> where Entity : class, IEntity, new()
{
public IDbConnection Db { get; set; }
#region HOOKS
protected SqlExpression<Entity> OnGetList(SqlExpression<Entity> query) { return query; }
protected SqlExpression<Entity> OnGetSingle(SqlExpression<Entity> query) { return OnGetList(query); }
#endregion
public List<Entity> GetAll()
{
var query = OnGetList(Db.From<Entity>());
return Db.Select(query);
}
public Entity GetById(long id)
{
var query = OnGetSingle(Db.From<Entity>())
.Where(e => e.Id == id);
var entity = Db.Single(query);
return entity;
}
}
Then we can use hooks like:
public interface IHello : IReadOnlyLogic<Hello> { }
public class HelloLogic : ReadOnlyLogic<Hello>, IHello
{
protected override SqlExpression<Hello> OnGetList(SqlExpression<Hello> query)
{
return query.Where(h => h.Name == "Something");
}
}
Finally our service only calls our logic:
public class MyServices : Service
{
IHello helloLogic;
public object Get()
{
return helloLogic.GetAll();
}
}