I am using Spring Cache #CacheEvict & #Cacheable
Currently I am running a scheduler every Hr to clear cache and next time when fetchUser() is called it will fetch data from external APi and add to cache.
#Scheduled(cron = "0 0 * * * *}")
#CacheEvict(value = "some-unique-value", allEntries = true)
public void clearUserCache() {
log.info("Cache cleared");
}
#Cacheable(value = "some-unique-value", unless = "#result.isFailure()")
#Override
public Result<UserResponse> fetchUser() {
try {
UserResponse userResponse = api.fetchUserDetail();
return Result.success(userResponse);
} catch (Exception e) {
return Result.failure(INTERNAL_SERVER_ERROR);
}
}
Now what we need is to clear cache only when User API call is success. Is there a way to do that.
As now cache is cleared on schedule and suppose external API call fails. Main API will return error response. In that case I should be able to use existing cache itself.
If I got it correctly, why don't you call it as a normal method after checking the API call is correct at this method's parent?
With your code, something along the lines of
// we just leave scheduled here as you need it.
#Scheduled(cron = "0 0 * * * *}")
#CacheEvict(value = "some-unique-value", allEntries = true)
public void clearUserCache() {
log.info("Cache cleared");
}
#Cacheable(value = "some-unique-value", unless = "#result.isFailure()")
#Override
public Result<UserResponse> fetchUser() {
try {
UserResponse userResponse = api.fetchUserDetail();
return Result.success(userResponse);
} catch (Exception e) {
return Result.failure(INTERNAL_SERVER_ERROR);
}
}
public void parentMethod() {
Result<UserResponse> userResult = this.fetchUser();
if(userResult.isFailure()) {
this.clearUserCache();
}
}
This way, if any Exception is thrown it will return with a failure status and you're able to check it. So the cache will be cleared either every hour or when it didn't work.
So the next time, as it was a failure and there's no cache, it will try again.
I didn't find any direct implementation but with a work around I was able to do it.
Use Case
User API response should be updated only when next service call is triggered which make use of User API. It should not be updated by scheduler. As we need to pass on header information coming in from external system, to User API as well.
Cache must be cleared only when User API response is success.
Steps:
Added a variable in scheduler and turning it ON on Schedule time and OFF when cache is updated.
This flag is used in UserService class to check if scheduler was triggered or not.
If not, use cache. If true, trigger User API call. Check for response, if success. Trigger CacheEvict method and update Cache.
Sample Code:
SchedulerConfig
private boolean updateUserCache;
#Scheduled(cron = "${0 0 * * * *}") // runs every Hr
public void userScheduler() {
updateUserCache = true;
log.info("Scheduler triggered for User");
}
#CacheEvict(value = "USER_CACHE", allEntries = true)
public void clearUserCache() {
updateUserCache = false;
log.info("User cache cleared");
}
public boolean isUserCacheUpdateRequired() {
return updateUserCache;
}
UserService
UserResponse userResponse = null;
if (schedulerConfig.isUserCacheUpdateRequired()) {
userResponse = userCache.fetchUserDetail();
if (userResponse != null) {
// clear's cache and userResponse is stored in cache automatically when getUserDetail is called below
schedulerConfig.clearUserCache();
}
}
return userCache.getUserDetail(userResponse);
UserCache
#Cacheable(value = "USER_CACHE", key = "#root.targetClass", unless = "#result.isFailure()")
public Result<User> getUserDetail(UserResponse userResponse) {
try {
if (userResponse == null) { // handle first time trigger when cache is not available
userResponse = fetchUserDetail(); // actual API call
}
return Result.success(mapToUser(userResponse));
} catch (Exception e) {
return Result.failure("Error Response");
}
}
Note:
Result is a custom Wrapper, assume it as a object which has success or failure attributes
I had to add #Cacheable part as separate Bean because caching only works on proxy objects. If I keep getUserDetail inside UserService and call directly, its not been intercepted as proxy and cache logic is not working, API call is triggered each time.
Most important: This is not the best solution and has scope for improvement.
I am using #RepositoryRestResource for Mongo Repositories.
I want to do some pre-save check and if those checks are not meeting the requirements, I want to abandon the save operation.
I tried :
#HandleBeforeSave
public void handleBeforeSave(CallLog callLog)
throws InternalServerException {
CallLog log = callRepository.findOne(callLog.getConferenceId());
if (log != null
&& (callLog.getStatus().equals(Constants.CALL_IN_PROGRESS) || callLog
.getStatus().equals(Constants.CALL_DROPPED))) {
if (callLog.getStatus().equals(Constants.CALL_DROPPED)) {
User user = userRepository.findOne(callLog.getReceiverId());
user.setStatus(Constants.USER_STATUS_IDLE);
userRepository.save(user);
}
throw new InternalServerException(
"This call has already been received");
} else {
User user = userRepository.findOne(callLog.getReceiverId());
user.setStatus(Constants.USER_STATUS_BUSY);
userRepository.save(user);
}
}
But throwing exception, does not actually abandon the save call. Is there any other way to do it?
You can use a RestController to intercept the request.
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RestController.html
I am totally new to Web API an am not understanding how to Filter get calls.
This method returns all items in my database.
// GET: api/LogEntries
public IQueryable<LogEntry> GetLogEntries()
{
return db.LogEntries;
}
This method returns a specific item in my database.
// GET: api/LogEntries/5
[ResponseType(typeof(LogEntry))]
public IHttpActionResult GetLogEntry(int id)
{
LogEntry logEntry = db.LogEntries.Find(id);
if (logEntry == null)
{
return NotFound();
}
return Ok(logEntry);
}
So now I want to filter the returned records so I created this method but it won't work because the specific item method gets called. I seem to be missing a concept and am hoping you can point me to more clear understanding. Thanks
// GET: api/LogEntries
public IQueryable<LogEntry> GetLogEntries(string levelID)
{
int levIdInt;
if (Int32.TryParse(levelID, out levIdInt))
{
return db.LogEntries.Take(300).Where(l => (int)l.Level == levIdInt).OrderByDescending(d => d.TimeStamp);
}
return db.LogEntries.Where(i => i.ID < 0);
}
You need to specify the route for that method
[Route("api/LogEntries/Level/{levelID}"]
public IQueryable<LogEntry> GetLogEntries(string levelID)
{}
More on routing is available here http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2
I'm reading the source of activejdbc, found these methods in ModelInstrumentation.
public void instrument(CtClass modelClass) throws Exception {
addDelegates(modelClass);
CtMethod m = CtNewMethod.make("public static String getClassName() { return \"" + modelClass.getName()
+ "\"; }", modelClass);
CtMethod getClassNameMethod = modelClass.getDeclaredMethod("getClassName");
modelClass.removeMethod(getClassNameMethod);
modelClass.addMethod(m);
}
CtClass modelClass = ClassPool.getDefault().get("org.javalite.activejdbc.Model");
private void addDelegates(CtClass target) throws NotFoundException, CannotCompileException {
CtMethod[] modelMethods = modelClass.getDeclaredMethods();
CtMethod[] targetMethods = target.getDeclaredMethods();
for (CtMethod method : modelMethods) {
if (Modifier.PRIVATE == method.getModifiers()) {
continue;
}
CtMethod newMethod = CtNewMethod.delegator(method, target);
if (!targetHasMethod(targetMethods, newMethod)) {
target.addMethod(newMethod);
} else {
System.out.println("Detected method: " + newMethod.getName() + ", skipping delegate.");
}
}
}
This class is used to enhance a model class, the first one instrument will firstly delegate all non-private methods from org.javalite.activejdbc.Model to its child model class, which means it will add such methods to the child:
public X f(...) {
return super.f(...);
}
I don't understand why it does this, since we can invoke these methods even if there is no delegates.
Explanation of this can be found in this discussion:
https://groups.google.com/forum/#!topic/activejdbc-group/l6KNBi5EPc0
Basically, the main problem is that the methods in the Model class that we need in a child class are static. Static classes in Java are not inherited. This means that when you do this:
Person.where(...)
You will be executing the method Model.where(), not the Person.where(), hence the framework would have no idea what table to query.
ActiveJDBC forces Model methods into child methods in order to at run time determine what table to go to for data.
I want to re-write a method that has way too many nested if statements.
I came up with this approach and wanted your opinions:
public void MyMethod()
{
bool hasFailed = false;
try
{
GetNewOrders(out hasFailed);
if(!hasFailed)
CheckInventory(out hasFailed);
if(!hasFailed)
PreOrder(out hasFailed);
// etc
}
catch(Exception ex)
{
}
finally
{
if(hasFailed)
{
// do something
}
}
}
I've done stuff similar to that, but without the exception handling:
BOOL ok = CallSomeFunction();
if( ok ) ok = CallSomeOtherFunction();
if( ok ) ok = CallYetAnotherFunction();
if( ok ) ok = WowThatsALotOfFunctions();
if( !ok ) {
// handle failure
}
Or if you want to be clever:
BOOL ok = CallSomeFunction();
ok &= CallSomeOtherFunction();
ok &= CallYetAnotherFunction();
...
If you are using exceptions anyway, why do you need the hasFailed variable?
Not really. Your methods should raise an exception in case of an error to be caught by your "catch" block.
As far as I can see this is an example of cascade steps where second and third one will be executed if first and first and second are valid, i.e. return hasFailed==false.
This code can be made much more elegant using Template Method and Decorator design pattern.
You need one interface, concrete implementation, abstract class and several subclasses of the abstract class.
public interface Validator {
public boolean isValid();
}
public class GetNewOrders implements Validator {
public boolean isValid() {
// same code as your GetNewOrders method
}
}
public abstract class AbstractValidator implements Validator {
private final Validator validator;
public AbstractValidator(Validator validator) {
this.validator = validator;
}
protected boolean predicate();
protected boolean isInvalid();
public final boolean isValid() {
if (!this.validator.isValid() && predicate() && isInvalid())
return false;
return true;
}
}
public class CheckInventory extends AbstractValidator {
public CheckInventory(Validator validator) {
super(validator);
}
#Override
public boolean predicate() {
return true;
}
#Override
public boolean isInvalid() {
// same code as your CheckInventory method
}
}
public class PreOrder extends AbstractValidator {
public CheckInventory(Validator validator) {
super(validator);
}
#Override
public boolean predicate() {
return true;
}
#Override
public boolean isInvalid() {
// same code as your PreOrder method
}
}
Now your method can look much more elegant:
public void MyMethod() {
bool success = false;
try {
Validator validator = new GetNewOrders();
validator = new CheckInventory(validator);
validator = new PreOrder(validator);
success = validator.isValid();
} finally {
if (!success) {
// do something
}
}
}
Validator object can be created in one line, but I prefer this style since it makes obvious the order of validation. Creating new validation link in the chain is matter of subclassing AbstractValidator class and implementation of predicate and isInvalid methods.
Without commenting on the try/catch stuff since I really don't know what is going on there, I would change it so the called methods return true/false for success and then just check them depending on the boolean short-circuiting to avoid calling later methods if the preceding method failed.
public void MyMethod()
{
bool success = false;
try
{
success = GetNewOrders()
&& CheckInventory()
&& PreOrder();
// etc
}
catch(Exception ex) { }
finally
{
if(!success)
{
}
}
}
This doesn't really look good to me. The use of the hasFailed variable is really not nice. if GetNewOrders fails with an exception, you for instance end up inside the catch block with hasFailed = false !
Opposed to other answers here I believe there MAY be legitimate uses for boolean "hasFailed" that are not exceptional. But I really don't think you should mix such a condition into your exception handler.
I know I'll probably duplicate a few posts: What's wrong with else? You could also use lazy evaluation (a() && b()) to link methods - but that relies on status being given as return value, which is more readable anyhow IMHO.
I don't agree with posters that you should raise an exception, because exceptions should be raised if program faults occur or the program enters an exceptional state because of operations. Exceptions are not business logic.
I would do it like this:
public void MyMethod()
{
bool success = false;
try
{
GetNewOrders(); // throw GetNewOrdersFailedException
CheckInventory(); // throw CheckInventoryFailedException
PreOrder(); // throw PreOrderFailedException
success = true;
}
catch( GetNewOrdersFailedException e)
{
// Fix it or rollback
}
catch( CheckInventoryFailedException e)
{
// Fix it or rollback
}
catch( PreOrderFailedException e)
{
// Fix it or rollback
}
finally
{
//release resources;
}
}
Extending an exception is rather trivial,
public NewExecption : BaseExceptionType {}
Well, I don't like code that appears to get a list of orders and then process them, and then stop processing them when an error occurs, when surely it should skip that order and move to the next? The only thing to completely fail on is when the database (source of orders, destination of preorders) dies. I think that the entire logic is a bit funky really, but maybe that's because I don't have experience in the language you are using.
try {
// Get all of the orders here
// Either in bulk, or just a list of the new order ids that you'll call the DB
// each time for, i'll use the former for clarity.
List<Order> orders = getNewOrders();
// If no new orders, we will cry a little and look for a new job
if (orders != null && orders.size() > 0) {
for (Order o : orders) {
try {
for (OrderItem i : o.getOrderItems()) {
if (checkInventory(i)) {
// Reserve that item for this order
preOrder(o, i);
} else {
// Out of stock, call the magic out of stock function
failOrderItem(o, i);
}
}
} catch (OrderProcessingException ope) {
// log error and flag this order as requiring attention and
// other things relating to order processing errors that aren't database related
}
}
} else {
shedTears();
}
} catch (SQLException e) {
// Database Error, log and flag to developers for investigation
}
Your new approach is not that bad for a simple set of instructions, but what happens when additional steps are added? Do you / would you ever require transactional behavior? (What if PreOrder fails? or If the next step after PreOrder fails?)
Looking forward, I would use the command pattern:
http://en.wikipedia.org/wiki/Command_pattern
...and encapsulate each action as a concrete command implementing Execute() and Undo().
Then it's just a matter of creating a queue of commands and looping until failure or an empty queue. If any step fails, then simply stop and execute Undo() in order on the previous commands. Easy.
Chris solution is the most correct. But I think you should not do more than you need. Solution should be extandable and that's enough.
Change value of a parameter is a bad practice.
Never use empty generic catch statement, at least add a comment why you do so.
Make the methods throw exception and handle them where it is appropriate to do so.
So now it is much more elegant :)
public void MyMethod()
{
try
{
GetNewOrders();
CheckInventory();
PreOrder();
// etc
}
finally
{
// do something
}
}