How to disable Caching at runtime if Couchbase connection failed? - java

I have a similar problem as asked here - How to disable Redis Caching at run time if redis connection failed. My application is using #Cacheable at the service layer for most of the database/static resources call.
Cache is backed by Couchbase and whenever application fails to connect Couchbase node application goes down. Which is what we are not expecting, we expect data should be served from the source system whenever connection failed.
We tried implementing CacheErrorHandler but it does not work as expected because we want to execute the actual method which is making a service call and return the response rather than logging the Cache fail, basically bypassing the cache and as soon as the Couchbase node is up or connection established get the data from cache.
Any idea how we can achieve it?

Thanks #Daniel Bickler for the suggestion, below is the implementation I written referring #John Blum answer.
CouchbaseCustomCacheManager:
import java.util.Map;
import org.springframework.cache.Cache;
import com.couchbase.client.spring.cache.CacheBuilder;
import com.couchbase.client.spring.cache.CouchbaseCacheManager;
public class CouchbaseCustomCacheManager extends CouchbaseCacheManager {
public CouchbaseCustomCacheManager(
final Map<String, CacheBuilder> initialCaches) {
super(initialCaches);
}
#Override
public Cache getCache(String name) {
return new CouchbaseCacheWrapper(super.getCache(name));
}
protected static class CouchbaseCacheWrapper implements Cache {
private final Cache delegate;
public CouchbaseCacheWrapper(Cache couchbaseCache) {
this.delegate = couchbaseCache;
}
#Override
public String getName() {
try {
return delegate.getName();
} catch (Exception e) {
return null;
}
}
#Override
public Object getNativeCache() {
try {
return delegate.getNativeCache();
} catch (Exception e) {
return null;
}
}
#Override
public ValueWrapper get(Object key) {
try {
return delegate.get(key);
} catch (Exception e) {
return null;
}
}
#Override
public <T> T get(Object key, Class<T> type) {
try {
return delegate.get(key, type);
} catch (Exception e) {
return null;
}
}
#Override
public void put(Object key, Object value) {
try {
delegate.put(key, value);
} catch (Exception e) {
try {
handleErrors(e);
} catch (Exception e1) {
}
}
}
#Override
public ValueWrapper putIfAbsent(Object key, Object value) {
try {
return delegate.putIfAbsent(key, value);
} catch (Exception e) {
return null;
}
}
#Override
public void evict(Object key) {
try {
delegate.evict(key);
} catch (Exception e) {
try {
handleErrors(e);
} catch (Exception e1) {
}
}
}
#Override
public void clear() {
try {
delegate.clear();
} catch (Exception e) {
try {
handleErrors(e);
} catch (Exception e1) {
}
}
}
protected <T> T handleErrors(Exception e) throws Exception {
if (e instanceof Exception) {
return null;
} else {
throw e;
}
}
}
}
And used it as:
#Bean
public CacheManager cacheManager() {
final Map<String, CacheBuilder> cache = new HashMap<>();
for (final String appCache : "127.0.0.1,127.0.0.2,127.0.0.3".split(",")) {
cache.put(appCache, CacheBuilder.newInstance(CouchbaseCluster.create().openBucket(
"default", "")));
}
return new CouchbaseCustomCacheManager(cache);
}

Related

Interuptiong active threads

I'm trying to interrupt active threads created in Restart() using Terminate() they both extend Event(). I have it set up so Terminate would change the value of terminate to true but I can't get the setter to change the value of terminate outside of Terminate():
Here is the relevant code:
Restart.java:
public class Restart extends Event {
...
public void action() {
...
for (int i = 0; i < eventList.size(); i++) {
Class<?> eventClass;
try {
eventClass = Class.forName(eventList.get(i));
Object eventObject;
if (eventList.get(i).equals("Bell")) {
eventObject = eventClass.getConstructor(long.class, int.class).newInstance(timeList.get(i), rings);
}
else {
eventObject = eventClass.getConstructor(long.class).newInstance(timeList.get(i));
}
eventThread = new Thread((Runnable) eventObject);
eventThread.start();
}
catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
Terminate.java
public class Terminate extends Event {
public Terminate(long delayTime) {
super(delayTime);
}
public void action() {
setTerminate(true);
System.out.println(getTerminate());
}
public String toString() {
return "Terminating";
}
}
Event.java
public abstract class Event implements Runnable {
...
public boolean terminate;
...
public void setTerminate(boolean terminate) {
this.terminate = terminate;
}
public boolean getTerminate() {
return terminate;
}
public void run() {
try {
Thread.sleep(delayTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
System.out.println(getTerminate());
while (getTerminate()) {
eventThread.interrupt();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
System.out.println(this.toString());
this.action();
}
catch (Exception e) {
e.printStackTrace();
}
}

How to regroup catch finally into one method in java 8?

New to java 8, I would like to optimise my code bellow:
public Response create() {
try{
...
} catch (Exception e) {
codeA;
} finally {
codeB;
}
}
public Response update() {
try{
...
} catch (Exception e) {
codeA;
} finally {
codeB;
}
}
I have a lot of methods using this same way to catch exceptions and do the same finally, is that possible to replace the bellow common code by a method in java 8? So that I could optimise all my methods who use this common code.
} catch (Exception e) {
codeA;
} finally {
codeB;
}
Depends what you do in the .... You could do something like this:
private Response method(Supplier<Response> supplier) {
try{
return supplier.get();
} catch (Exception e) {
codeA;
} finally {
codeB;
}
}
and invoke like:
public Response create() { return method(() -> { ... for create }); }
public Response update() { return method(() -> { ... for update }); }
You could wrap your payload and put it to the separate method. One thing; what do you expect to return on exception catch. This time this is null, but probably you could provide default value.
public static <T> T execute(Supplier<T> payload) {
try {
return payload.get();
} catch(Exception e) {
// code A
return null;
} finally {
// code B
}
}
Client code could look like this:
public Response create() {
return execute(() -> new CreateResponse());
}
public Response update() {
return execute(() -> new UpdateResponse());
}
This could be a generic solution.
//here describe supplier which can throw exceptions
#FunctionalInterface
public interface ThrowingSupplier<T> {
T get() throws Exception;
}
// The wrapper
private <T> T callMethod(ThrowingSupplier<T> supplier) {
try {
return supplier.get();
} catch (Exception e) {
//code A
}finally {
// code B
}
}

Non-Static Generic function that invokes a method passed in as a parameter

I'm trying to consolidate 2 methods into 1, because they handle exceptions the same way. I know in C# you can pass functions/actions as parameters into other functions. I tried creating a generic method to invoke a function, but can't seem to figure it out.
public String getTheStuff(String client) {
try {
return extService.getProduct(client);
} catch (UIException e) {
notHealthy();
} catch (HostException e) {
notHealthy();
} catch (Exception e) {
Throwables.propagate(e);
}
}
public CustomType getsomeMoreStuff(String source, int offset) {
try {
return extService.getMetrics(source, offset);
} catch (UIException e) {
notHealthy();
} catch (HostException e) {
notHealthy();
} catch (Exception e) {
Throwables.propagate(e);
}
}
What I'm looking for is something like
public T invokeExtService(Function functionToInvoke, Parameters[] params){
try {
return functionToInvoke.Invoke(params);
} catch (UIException e) {
notHealthy();
} catch (HostException e) {
notHealthy();
} catch (Exception e) {
Throwables.propagate(e);
}
}
As #LouisWasserman said, this would be much nicer in Java 8, but how about something like this (untested):
public <T> T invoke(Callable<T> function) {
try {
return function.call();
} catch (UIException e) {
notHealthy();
} catch (HostException e) {
notHealthy();
} catch (Exception e) {
Throwables.propagate(e);
}
}
public String getTheStuff(final String client) {
return invoke(new Callable<String>() {
#Override
public String call() {
return extService.getProduct(client);
}
});
}
public CustomType getsomeMoreStuff(final String source, final int offset) {
return invoke(new Callable<CustomType>() {
#Override
public CustomType call() {
return extService.getMetrics(source, offset);
}
});
}
To be honest, I'm not sure how worthwhile this is considering how short your methods are (and they could be even shorter with multi-catch).

how to use generic jsonFile handler using guice?

I have 2 repositories classes:
public class ResponseRepository implements IRoutingResponseRepository {
private final String baselineFileName;
#Inject
#Singleton
public ResponseRepository(#Named("baseline_file") String baselineFileName) {
this.baselineFileName = baselineFileName;
}
#Override
public E2EResult getBaseLine() {
E2EResult e2EResult = null;
ObjectMapper mapper = new ObjectMapper();
try
{
e2EResult = mapper.readValue(new File(baselineFileName), E2EResult.class);
} catch (JsonGenerationException e)
{
e.printStackTrace();
} catch (JsonMappingException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return e2EResult;
}
}
and
public class StatsRepository implements IRoutingResponseRepository {
private final String baselineFileName;
#Inject
#Singleton
public StatsRepository(#Named("stats_file") String baselineFileName) {
this.baselineFileName = baselineFileName;
}
#Override
public StatsObj getStats() {
StatsObj statsObj = null;
ObjectMapper mapper = new ObjectMapper();
try
{
statsObj = mapper.readValue(new File(baselineFileName), StatsObj.class);
} catch (JsonGenerationException e)
{
e.printStackTrace();
} catch (JsonMappingException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return statsObj;
}
}
how can I refactor the common code to be generic one?
and also I want guice to use fileName = E2EResult.csv when <E2EResult> and fileName = StatsObj.csv when <StatsObj>
I have tried:
but I wrote the generics incorrectly. It shows an error.
And also i'm not sure how to let guice inject different fileName
public interface IFileHandler<T> {
T getContent();
}
and
public class JsonFileHandler implements IFileHandler<T> {
String fileName;
#Inject
public JsonFileHandler(String file) {
this.fileName = file;
//Constants.RESULTS_BASELINE_FILE
}
public <T> T getContent() {
T t = null;
ObjectMapper mapper = new ObjectMapper();
try {
t = mapper.readValue(new File(fileName), T.class);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return t;
}
}
For the type variable part, it would be, with this interface:
public interface IFileHandler<T> {
T getContent();
}
this implementing class declaration and method signature:
class JsonFileHandler<T> implements IFileHandler<T> {
public T getContent() {
T t = null;
// ...
return t;
}
}

Spring Batch :Aggregated reader / writer Issue

I am trying to use Spring batch and implement an aggregated reader (batch file, where multiple records should be treated as one record while writing). Here is the code snippet for my reader:
public class AggregatePeekableReader implements ItemReader<List<T>>, ItemStream {
private SingleItemPeekableItemReader<T> reader;
private boolean process(T currentRecord , InvoiceLineItemsHolder holder) throws UnexpectedInputException, ParseException, Exception {
next = peekNextInvoiceRecord();
// finish processing if we hit the end of file
if (currentRecord == null ) {
LOG.info("Exhausted ItemReader ( END OF FILE)");
holder.exhausted = true;
return false;
}
if ( currentRecord.hasSameInvoiceNumberAndVendorNumber(next)){
LOG.info("Found new line item to current invocie record");
holder.records.add(currentRecord);
currentRecord = null;
return true;
}else{
holder.records.add(currentRecord);
return false;
}
}
private T getNextInvoiceRecord () {
T record=null;
try {
record=reader.read();
} catch (UnexpectedInputException e) {
ALERT.error(LogMessageFormatter.format(Severity.HIGH,
BATCH_FILE_READ_EXCEPTION, e), e);
throw e;
} catch (ParseException e) {
ALERT.error(LogMessageFormatter.format(Severity.HIGH,
BATCH_FILE_READ_EXCEPTION, e), e);
throw e;
} catch (Exception e) {
ALERT.error(LogMessageFormatter.format(Severity.HIGH,
BATCH_FILE_READ_EXCEPTION, e), e);
}
return record;
}
private T peekNextInvoiceRecord() {
T next=null;
try {
next=reader.peek();
} catch (UnexpectedInputException e) {
ALERT.error(LogMessageFormatter.format(Severity.HIGH,
BATCH_FILE_READ_EXCEPTION, e), e);
throw e;
} catch (ParseException e) {
ALERT.error(LogMessageFormatter.format(Severity.HIGH,
BATCH_FILE_READ_EXCEPTION, e), e);
throw e;
} catch (Exception e) {
ALERT.error(LogMessageFormatter.format(Severity.HIGH,
BATCH_FILE_READ_EXCEPTION, e), e);
}
return next;
}
public void close () {
reader.close();
}
public SingleItemPeekableItemReader<T> getReader() {
return reader;
}
public void setReader(SingleItemPeekableItemReader<T> reader) {
this.reader = reader;
}
private class InvoiceLineItemsHolder {
List<T> records = new ArrayList<T>();
boolean exhausted = false;
}
#Override
public void open(ExecutionContext executionContext) throws ItemStreamException {
//
reader.open(executionContext);
}
#Override
public void update(ExecutionContext executionContext) throws ItemStreamException {
// TODO
}
#Override
public List<T> read() throws Exception, UnexpectedInputException, ParseException,
NonTransientResourceException {
CLASS holder = new SOMECLASS()
synchronized (this) {
while (process(getNextInvoiceRecord(), holder)) {
continue;
}
if (!holder.exhausted) {
return holder.records;
} else {
//When you hit the end of the file,close the reader.
close();
return null;
}
}
}
}
The above is a working example for implementing a peekable reader.This peeks the next line
(doesnt read it) and determines whether a logical end of line is reached (some times
multiple lines can make up a single transaction)
You need to implement ItemStream interface for reader. This will give a hint to Spring Batch, that your reader requires some actions to open/close a stream:
public class InvoiceLineItemAggregatePeekableReader extends AbstractItemStreamItemReader<List<SAPInvoicePaymentRecord>> {
#Override
public void close() {
...
}
}
Streams are closed whatever error occurred during step execution. For more examples check classes from Spring Batch itself (e.g. FlatFileItemReader).
I can't move the input file to to an Error folder because the Reader
is not closed
you could copy the file and either use File.deleteOnExit() on the old file for later deletion or delete the old file in an extra step, e.g. with a simple tasklet and a flow which calls the deleteTaskletStep only if the business step had an exception

Categories

Resources