How to pass parameter value to aspect - spring-aop

How do we get the parameter value(uId) from calling method(deleteTask) of JointPoint(in logJdbcOperation)? I am able to log sql statement and sql parameters but cannot find a way to log value of uId.
Please, guide me.
public int deleteTask(String taskname, String uId) {
String sql = "delete from shedlock where NAME= :name";
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
((MapSqlParameterSource) namedParameters).addValue("name", taskname, Types.VARCHAR);
return namedJdbcTemplate.update(sql, namedParameters);
}
#Aspect
#Component
public class LoggingAspect {
private static final Logger LOGGER = LogManager.getLogger(LoggingAspect.class);
#Before("execution(* org.springframework.jdbc.core..NamedParameterJdbcOperations.*(String, ..))")
public void logJdbcOperation(JoinPoint jp) {
Object[] methodArgs = jp.getArgs();
String statement = methodArgs[0].toString();
MapSqlParameterSource params = (MapSqlParameterSource)methodArgs[1];
LOGGER.debug("SQL statement:" + statement);
}
}

The code shared does not show how the uId is passed on to the method namedJdbcTemplate.update(sql, namedParameters). It is not possible to get the parameter to the calling method . Any parameter of the target method can be obtained.
Following code would advice the method deleteTask and get the arguments passed to it.
#Around("execution(* package.deleteTask(..)) && args(taskName,uId)")
public Object logDeleteTask(ProceedingJoinPoint pjp, String taskName, String uId) {
LOGGER.debug("Task Name :" + taskName);
LOGGER.debug("Uid :" + uId);
Object ret = 0;
try {
ret = pjp.proceed();
} catch (Throwable e) {
// handle exception if any
}
return ret;
}
Reference : Passing Parameter to Advice
Note : Remember to modify the package.deleteTask(..) to approrpriate package name.

Related

Overriding Hystrix command properties specified in .properties file

I need to override command timeout property specified in my application.properties file. Here is what I tried
#Test
public void testTokenQueryTimeout() throws Exception
{
String propertyToSet ="hystrix.command.quickbaseTokenQueryCommand.execution.isolation.thread.timeoutInMilliseconds";
String prop="";
try {
prop = ConfigurationManager.getConfigInstance().getProperty(
propertyToSet).toString();
logger.info("\n\n\noriginal quickbaseTokenQueryCommand timeout ="+prop);
System.setProperty(
propertyToSet,"10");
prop = ConfigurationManager.getConfigInstance().getProperty(
propertyToSet).toString();
logger.info("\n\n\nupdated quickbaseTokenQueryCommand timeout ="+prop);
String response = accountValidation.isValidToken(token);
logger.info(response);
Assert.assertFalse(true);
}
catch (AccountValidationServiceException e)
{
Assert.assertTrue(Constants.ERRCODE_TOKEN_QUERY_TIMED_OUT.equals(e.getErrorCode()));
}
finally {
ConfigurationManager.getConfigInstance().clearProperty(propertyToSet);
System.clearProperty(propertyToSet);
if(!GeneralUtil.isObjectEmpty(System.getProperty(
propertyToSet)))prop = System.getProperty(
propertyToSet);
logger.info("Updated testTokenQueryTimeout timeout ="+prop);
}
}
Notice, System.setProperty(propertyToSet,"10"). With this approach this test case passes i.e. the property gets changed and command times out but another test case fails due to this command timeout though I am clearing the property from System.
I also tried setting the property using ConfigurationManager.getConfigInstance().setProperty(
propertyToSet).toString(),"10"); But in that case, this change of property has no effect and command does not timeout.
Is there something I am missing here.
Please help.
Try using the ConcurrentCompositeConfiguration class
application.properties
hystrix.command.HelloWorldCommand.execution.isolation.thread.timeoutInMilliseconds=200
Command
public class HelloWorldCommand extends HystrixCommand<String> {
public HelloWorldCommand() {
super(HystrixCommandGroupKey.Factory.asKey("HelloWorldGroup"));
}
#Override
protected String run() throws Exception {
TimeUnit.MILLISECONDS.sleep(1100);
return "Hello";
}
}
Test
public class HelloWorldCommandTest {
#Test
public void commandConfigTest() {
String propertyKey = "hystrix.command.HelloWorldCommand.execution.isolation.thread.timeoutInMilliseconds";
ConcurrentCompositeConfiguration config = (ConcurrentCompositeConfiguration) ConfigurationManager.getConfigInstance();
Integer originalTimeout = (Integer) config.getProperty(propertyKey);
config.setOverrideProperty(propertyKey, 1200);
String result = new HelloWorldCommand().execute();
assertThat(result, is("Hello"));
config.setOverrideProperty(propertyKey, originalTimeout);
Integer timeoutValue = (Integer) config.getProperty(propertyKey);
assertThat(timeoutValue, is(originalTimeout));
}
}

Exception when trying to use DynamoDBMapper: no mapping for HASH key

I have a DynamoDB table with a primary key (id : integer) and secondary key (dateTo : String). I've made a Class that utilizes DynamoDBMapper:
#DynamoDBTable(tableName="MyItems"
public class MyItemsMapper {
private int id;
private String dateTo;
private String name;
#DynamoDBHashKey(attributeName="id")
public void setId(int id) { this.id = id; }
public int getId() { return id; }
#DynamoDBAttribute(attributeName="dateTo")
public void setDateTo(String dateTo) { this.dateTo = dateTo; }
public String getDateTo() { return dateTo; }
#DynamoDBAttribute(attributeName="name")
public void setName(String name { this.name = name; }
public String getName() { return name; }
public boolean saveItem(MyItemsMapper item) {
try {
DynamoDBMapper mapper = new DynamoDBMapper(client); //<-- This connects to the DB. This works fine.
item.setId(generateUniqueNumber()); //<-- This generates a unique integer. Also seems to work fine.
mapper.save(item);
logger.info("Successfully saved item. See info below.");
logger.info(item.toString());
return true;
} catch (Exception e) {
logger.error("Exception while trying to save item: " + e.getMessage());
e.printStackTrace();
return false;
}
}
}
I then have a manager class that uses the bean above, like so:
public class MyManager {
public boolean recordItem(
int id,
String dateTo,
String name,
) {
MyItemsMapper myItemsMapper = new MyItemsMapper();
myItemsMapper.setId(id);
myItemsMapper.setDateTo(dateTo);
myItemsMapper.setName(name);
myItemsMapper.saveItem(myItemsMapper);
}
}
I am running the manager class in a JUnit test:
public class MyManagerTest {
#Test
public void saveNewItemTest() {
MyManager myManager = new MyManager();
myManager.recordItem(1234567, "2018-01-01", "Anthony");
}
}
When I use the saveItem method above via my manager by running my JUnit test, I get the following error:
com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException: MyItemsMapper; no mapping for HASH key
Not really sure what it's pertaining to, as I definitely have a primary key for my table and my secondary key always has a value as well.
How do I get this to work?
More Info:
It's worth noting that I can record data into my DynamoDB table via the Item object. If I do the below, my data gets recorded into the database:
DynamoDB dynamoDB = new DynamoDBClient().connectToDynamoDB(); //<--
Connection. Works fine.
Table table = dynamoDB.getTable("MyItems");
item.withPrimaryKey("id", 1234567);
item.withString("dateTo", "2018-01-01");
item.withString("name", "Anthony");
PutItemOutcome outcome = table.putItem(item);
However, I'm trying to use DynamoDBMapper because I'm reading that it is a more organized, better way to access data.
Im not sure if this is causing the problem, but you are creating the myItemsMapper object, then passing a reference to this object to itself.
I would suggest removing your saveItem method. The MyItemsMapper class should be a plain old java object. Then make MyManager like this
public class MyManager {
public boolean recordItem(
int id,
String dateTo,
String name,
) {
MyItemsMapper myItemsMapper = new MyItemsMapper();
myItemsMapper.setId(id);
myItemsMapper.setDateTo(dateTo);
myItemsMapper.setName(name);
DynamoDBMapper mapper = new DynamoDBMapper(client);
mapper.save(myItemsMapper);
}
}
If you particularly want to keep the saveItem method make it like this
public boolean saveItem() {
try {
DynamoDBMapper mapper = new DynamoDBMapper(client);
mapper.save(this);
logger.info("Successfully saved item. See info below.");
logger.info(this.toString());
return true;
} catch (Exception e) {
logger.error("Exception while trying to save item: " + e.getMessage());
e.printStackTrace();
return false;
}
}
And then in MyManager do
MyItemsMapper myItemsMapper = new MyItemsMapper();
myItemsMapper.setId(id);
myItemsMapper.setDateTo(dateTo);
myItemsMapper.setName(name);
myItemsMapper.saveItem();

Read data from Firebase

I'm using Firebase for my Android app, I want read datas. In particular I want to select an user with a specific id. When I use the debugger it seems that the code doesn't execute the onDataChange() instruction.
private User readUserById(){
final User u = new User("","","");
Query query = mDatabaseReferences.child("users").orderByChild("id").equalTo(id);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()){
u.setId(ds.child("id").getValue(User.class).getId());
u.setNumber((ds.child("number").getValue(User.class).getNumber()));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return u;
}
private void initFirebase() {
FirebaseApp.initializeApp(this);
mFirebaseDatabase = FirebaseDatabase.getInstance();
mDatabaseReferences = mFirebaseDatabase.getReference();
}
public void sendCode(View v){
id= id.getText().toString();
readUserById();
phoneNumber = phoneText.getText().toString();
if (phoneNumber.equals("") || id.equals("")) {
Toast t = Toast.makeText(this, "Please insert a nickname and a valid phone number", Toast.LENGTH_LONG);
t.show();
} else {
setUpVerificationCallbacks();
PhoneAuthProvider.getInstance().verifyPhoneNumber(
phoneNumber,
60,
TimeUnit.SECONDS,
this,
verificationCallbacks
);
}
// }
}
Using the debugger I've seen that the 'id' value is correct.
I used Firebase documentation for sendCode(), the user registration works correctly, just like the sms sending. I want to check if the nickname already exists, and the value is in the 'id' Textview. I call the sendCode() through a button.
I've tried in this way but doesn't work. Running with the debugger the result of user is null
private User readUserByName(){
final User[] user = {new User()};
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.child("users").child(nick).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
user[0] = dataSnapshot.getValue(User.class);
Log.d("Tag", user[0].toString());
}
else
Log.e("Tag","No such user exists");
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return user[0];
}
This is how I save the User
I've launched the app with the debugger
Assuming that users node is a direct child of your Firebase root, please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference testRef = rootRef.child("users").child("test");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String id = dataSnapshot.child("id").getValue(String.class);
String idName = dataSnapshot.child("idName").getValue(String.class);
String number = dataSnapshot.child("number").getValue(String.class);
Log.d("TAG", id + " / " + idName + " / " + number);
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
testRef.addListenerForSingleValueEvent(eventListener);
The output will be:
test / f70eb... / number
Assumed that :
node "users" directly under root node.
You already know the id of the user and this id contains all the information under User.class
You only want to read a user, if exists in database.
All the getters and setter exists in User.class and a Public empty constructor exists
Here is how you should do it
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.child("users").ref(id).addListenerforSingleValueEvent(listener);
And in Listener's OnDataChange(DataSnapshot snap);
if(snap.exists()){
user = snap.getValue(User.class);
Log.d("Tag",user.toString());
}
else
Log.e("Tag","No such user exists");

GWT Restlet Parameters Always Null

I am brand new to both REST and RESTlet- I got everything up and communicating last night but what I found this morning is that everything I pass into the server is always becoming null.
just as a sample app i have the following - a User Objectify entity (id, emailAddress, and version), and a RESTUserProxy object (id, emailAddress) - I wasn't originally sure if i could pass Objectify Entities back and after not being able to see anything switched it to the Proxy object - if i can get it to work this way I will try switching it back
the front end is as follows:
public interface RESTUserResourceProxy extends ClientProxy {
#Get
public void find(String emailAddress, Result<RESTUserProxy> callback);
#Put
public void persist(RESTUserProxy user, Result<Void> callback);
#Delete
public void delete(RESTUserProxy user, Result<Void> callback);
}
the backend code is as follows (this is currently extremely ugly - i got a little frustrated just trying to see something and put in a ton of sysouts)
public class RESTUserServerResource extends ServerResource implements RESTUserResource {
private final UserDao userDao;
public RESTUserServerResource() {
System.out.println("CREATED USER RESOURCE IMPL");
userDao = new UserDao();
}
#Override
#Get
public RESTUserProxy find() {
System.out.println("reference = " + getReference());
Form queryParams = getReference().getQueryAsForm();
System.out.println("query params = " + queryParams);
System.out.println("query = " + getQuery());
System.out.println("query string = " + getQuery().getQueryString());
String searchQuery = (String) getRequest().getAttributes().get("searchQuery");
System.out.println("search query = " + searchQuery) ;
return null;
// if (emailAddress == null) {
// return null;
// }
// System.out.println("user resource impl find [" + emailAddress + "]");
// final User user = userDao.find(emailAddress.getText());
// if (user != null) {
// System.out.println("found user ");
// return new RESTUserProxy(user.getId(), user.getEmailAddress());
// } else {
// System.out.println("found absolutely nothing");
// return null;
// }
}
#Override
#Put
public void persist(RESTUserProxy userProxy) {
System.out.println("user proxy = " + userProxy);
if (userProxy == null) {
return;
}
final User user = userDao.find(userProxy.getId());
user.setEmailAddress(userProxy.getEmailAddress());
user.setId(userProxy.getId());
userDao.persist(user);
}
#Override
#Delete
public void delete(RESTUserProxy userProxy) {
final User user = userDao.find(userProxy.getId());
userDao.delete(user);
}
}
what im having problems with is that eerythings coming through as null - a lot of other answers on here said to get the query to get the params - but here the query is null
below is the output of calling find and persist
reference = http://127.0.0.1:8888/users/123
query params = []
query = []
query string =
search query = null
i'm sure i'm doing something stupid here i just have no idea how to proceed right now. Any help as to what i'm doing wrong would be greatly appreciated.
This is due to GAE not supporting chunked encoding. See workaround here:
http://wiki.restlet.org/docs_2.1/13-restlet/21-restlet/318-restlet/303-restlet.html#dsy303-restlet_gwt

No Viable Alternative at character ' '

Hi i am getting the following error in this code
/*
Class : CreateMobileChatterCntrl
Description : Post Chatter on Contact.
Developed by : Harish Khatri(Appirio Offshore)
Created Date : June 2, 2012
*/
public without sharing class CreateMobileChatterCntrl {
public final Id ContactID{get;set;}
public String message{get;set;}
public boolean isSuccess{get;set;}
public boolean throwError{get;set;}
public String deviceType{get;set;}
//----------------------------------------------------------------------------
//constructor
//----------------------------------------------------------------------------
public CreateMobileChatterCntrl() {
throwError = false;
isSuccess = false;
if( ApexPages.CurrentPage().getParameters().get('id') != null){
ContactID = ApexPages.CurrentPage().getParameters().get('id');
}
String userAgent = ApexPages.currentPage().getHeaders().get('USER-AGENT');
if(userAgent.contains('iPhone'))
deviceType = 'iPhone';
//else if(userAgent.contains('Android')) deviceType = 'Android';
}
//----------------------------------------------------------------------------
// Post the chatter on contact
//----------------------------------------------------------------------------
public Pagereference save() {
if(message == null || message ==''){
throwError = true;
return null;
}
FeedItem feedItem = new FeedItem();
feedItem.ParentId = ContactID;
feedItem.Body = message;
try {
insert feedItem;
isSuccess = true;
} catch(Exception e){}
return null;//new PageReference('/' + ContactID);
}
public Pagereference cancel() {
return new PageReference('/' + ContactID);
}
}
public final Id ContactID{get;set;} at this line i am getting the error No Viable Alternative at character ' '.can any one please help why i am getting this error??
Some of the single quote characters in your class file are invalid --- perhaps because you copied and pasted the code from somewhere else. I've had this happen many times before when I've copied code from elsewhere. Starting with the quotes in: message == '' , i'd delete the single quotes, retype them, and resave your file. Repeat for all single quotes (or do a find and replace).

Resources