I recently went through a code review, and it was firmly suggested that I consolidate two methods into one. Both methods are identical, save for a single method call in each, and one does not require an argument.
Method #1
private void updateCache(List<CategoryObject> objectList) {
ServiceApi serviceApi = getService();
if (serviceApi != null) {
try {
serviceApi.updateResources(objectList);
} catch (BusinessException e) {
log.error(e);
}
}
}
Method #2
private void registerCache() {
ServiceApi serviceApi = getService();
if (serviceApi != null) {
try {
serviceApi.registerCategory(CATEGORY_NAME);
} catch (BusinessException e) {
log.error(e);
}
}
}
Can these even be efficiently combined?
You can pull the inner functionality out into an interface:
private interface Op {
void perform(ServiceApi serviceApi);
}
static void cache(Op op) {
ServiceApi serviceApi = getService();
if (serviceApi != null) {
try {
op.perform(serviceApi);
} catch (BusinessException e) {
log.error(e);
}
}
}
private void updateCache(List<CategoryObject> objectList) {
cache(new Op() {
#Override
public void perform(ServiceApi serviceApi) {
serviceApi.updateResources(objectList);
}
});
}
private void registerCache() {
cache(new Op() {
#Override
public void perform(ServiceApi serviceApi) {
serviceApi.registerCategory(CATEGORY_NAME);
}
});
}
In Java 8 the two methods become truly simple and elegant.
private void updateCache(List<CategoryObject> objectList) {
cache(serviceApi -> serviceApi.updateResources(objectList));
}
private void registerCache() {
cache(serviceApi -> serviceApi.registerCategory(CATEGORY_NAME));
}
You could just use one method and differentiate by the input parameter:
private void updateCache(List<CategoryObject> objectList) {
ServiceApi serviceApi = getService();
if (serviceApi != null) {
try {
if(objectList != null){
serviceApi.updateResources(objectList);
}
else{
serviceApi.registerCategory(CATEGORY_NAME);
}
} catch (BusinessException e) {
log.error(e);
}
}
}
Maybe the method name should be refactored as well then: handleCache()?
You then can call the method in 2 ways:
handleCache(objectList) --> works like method #1
handleCache(null) --> works like method #2
Related
I have a method that receives a dto in which many of its fields are used to make a dynamic query based on the non-null fields.
I am accessing each field by reflection in a lambda to add the non-null fields to the dynamic query. This works, but I don't know how to get that list to return it.
#Override
public List<AirlinePreOrderDto> getPreorders(AirlinePreOrderDto airlinePreOrderDto) {
PreOrder entity = PreOrderMapper.mapToJpaEntity(airlinePreOrderDto);
Query dynamicQuery = new Query();
ReflectionUtils.doWithLocalFields(entity.getClass(), field -> {
field.setAccessible(true);
try {
if (field.get(entity) != null) {
if (!field.getName().equals("serialVersionUID")) {
if(field.getName().equals("preorderId")) {
dynamicQuery.addCriteria(Criteria.where(field.getName()).is(field.get(entity)));
} else {
dynamicQuery.addCriteria(Criteria.where(field.getName()).is(field.get(entity)));
}
}
List<AirlinePreOrderDto> result = PreOrderMapper
.mapToDtos(mongoTemplate.find(dynamicQuery, PreOrder.class, "preorders"));
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
});
// return result list;
}
I suggest you to use an enclosing class.
class EnclosingResults {
List<AirlinePreOrderDto> results;
public void setResults(List<AirlinePreOrderDto> results) {
this.results = results;
}
public List<AirlinePreOrderDto> getResults() {
return results;
}
}
So your method will be:
#Override
public List<AirlinePreOrderDto> getPreorders(AirlinePreOrderDto airlinePreOrderDto) {
PreOrder entity = PreOrderMapper.mapToJpaEntity(airlinePreOrderDto);
Query dynamicQuery = new Query();
EnclosingResults resultEncloser = new EnclosingResults();
ReflectionUtils.doWithLocalFields(entity.getClass(), field -> {
field.setAccessible(true);
try {
if (field.get(entity) != null) {
if (!field.getName().equals("serialVersionUID")) {
if(field.getName().equals("preorderId")) {
dynamicQuery.addCriteria(Criteria.where(field.getName()).is(field.get(entity)));
} else {
dynamicQuery.addCriteria(Criteria.where(field.getName()).is(field.get(entity)));
}
}
List<AirlinePreOrderDto> result = PreOrderMapper
.mapToDtos(mongoTemplate.find(dynamicQuery, PreOrder.class, "preorders"));
resultEncloser.setResults(result);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
});
return resultEncloser.getResults()
}
It seems that you don't want to call mongoTemplate.find or PreOrderMapper.mapToDtos inside of the lambda, as the lambda will be executed once for each local field.
But from your code I'd guesstimate that you really want to execute the query after having built the dynamicQuery object from all fields.
And since you already manipulate the object referenced by dynamicQuery inside the lambda, it's as simple as moving the code to actually execute it out of the lambda:
PreOrder entity = PreOrderMapper.mapToJpaEntity(airlinePreOrderDto);
Query dynamicQuery = new Query();
ReflectionUtils.doWithLocalFields(entity.getClass(), field -> {
field.setAccessible(true);
try {
if (field.get(entity) != null) {
if (!field.getName().equals("serialVersionUID")) {
if(field.getName().equals("preorderId")) {
dynamicQuery.addCriteria(Criteria.where(field.getName()).is(field.get(entity)));
} else {
dynamicQuery.addCriteria(Criteria.where(field.getName()).is(field.get(entity)));
}
}
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
});
List<AirlinePreOrderDto> result = PreOrderMapper
.mapToDtos(mongoTemplate.find(dynamicQuery, PreOrder.class, "preorders"));
return result;
Update: came up with new error about the provided java class
I have a tutorial for building an app for an external barcode scanner(use USB port) by using Java + provided Jar Library. I'm trying to build the same app by using the Xamarin.Forms and that Jar Library(through BindingsLibrary Project). However, I got an error
"Java.Lang.NoClassDefFoundError: " when I compiled my code. Does anybody have an idea about what I'm doing wrong?
This my java classes:
The USBScanFactory
package com.unistrong.qrcode;
import com.unistrong.pin.GOPOManager;
public class USBQRscanFactory {
private static USBQRscanFactory factory = new USBQRscanFactory();
static boolean mIsScanContinue = false;
private GOPOManager mGopoManager = GOPOManager.getInstance();
private OnScanListener mScanListener;
private QRScanManagerJNI qrScanManagerJNI;
private USBQRscanFactory() {
}
public static USBQRscanFactory createInstance() {
return factory;
}
public void init(OnScanListener onScanListener) {
this.mGopoManager.Pin11_High();
this.qrScanManagerJNI = new QRScanManagerJNI(onScanListener);
this.qrScanManagerJNI.callbackInit();
}
public void enableAddKeyValue(int i) {
QRScanManagerJNI.AddKeyValue(i);
}
public void open() {
this.mGopoManager.Pin11_Low();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
QRScanManagerJNI.OpenDev();
}
public void powerOn() {
this.mGopoManager.Pin11_High();
this.mGopoManager.openPower5V_3V3();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void powerOff() {
this.mGopoManager.Pin11_High();
this.mGopoManager.closePower5V_3V3();
}
public void scan_start() {
QRScanManagerJNI.QRScan();
}
On ScanListener:
package com.unistrong.qrcode;
public interface OnScanListener {
void scanReport(byte[] bArr);
void statusReport(int i);
}
And here is my code on Xamain:
public class OnScanListener : Java.Lang.Object, IOnScanListener
{
H myH = new H();
public void ScanReport(byte[] byteArray)
{
lock (myH)
{
if (null != byteArray && byteArray.Length > 0)
{
myH.SendMessage(myH.ObtainMessage(0, byteArray));
}
}
}
public void StatusReport(int i)
{
lock (myH)
{
myH.SendEmptyMessage(i);
}
}
}
#endregion
public MainPage()
{
usbScan = USBQRscanFactory.CreateInstance();
InitializeComponent();
}
int count = 0;
private void scanBtn_Clicked(object sender, EventArgs e)
{
count++;
//usbScan.Init(OnScanListener);
OnScanListener myOnScanListener = new OnScanListener();
usbScan.PowerOn();
usbScan.Init(myOnScanListener);
Barcode.Text = "";
openScanner(true);
usbScan.Scan_start();
}
//Open Scanner
private void openScanner(bool open)
{
if (open == mWorkingStateFlag) return;
if (open)
{
try
{
Java.Lang.Thread.Sleep(50);
usbScan.Open();
usbScan.EnableAddKeyValue(0);
}
catch (Java.Lang.InterruptedException e)
{
// TODO Auto-generated catch block
e.PrintStackTrace();
}
}
}
I'm using an asyncronus XML-RPC-Client (https://github.com/gturri/aXMLRPC) in my Project and wrote some methods using the asyncronous Callback-Methods of this Client like this this:
public void xmlRpcMethod(final Object callbackSync) {
XMLRPCCallback listener = new XMLRPCCallback() {
public void onResponse(long id, final Object result) {
// Do something
if (callbackSync != null) {
synchronized (callbackSync) {
callbackSync.notify();
}
}
}
public void onError(long id, final XMLRPCException error) {
// Do something
if (callbackSync != null) {
synchronized (callbackSync) {
callbackSync.notify();
}
}
}
public void onServerError(long id, final XMLRPCServerException error) {
Log.e(TAG, error.getMessage());
if (callbackSync != null) {
synchronized (callbackSync) {
callbackSync.notifyAll();
}
}
}
};
XMLRPCClient client = new XMLRPCClient("<url>");
long id = client.callAsync(listener, "<method>");
}
In other methods I like to call this method (here "xmlRpcMethod") and wait until it finished. I wrote methods like this:
public void testMethod(){
Object sync = new Object();
xmlRpcMethod(sync);
synchronized (sync){
try{
sync.wait();
}catch(Interrupted Exception e){
e.printStackTrace();
}
}
// Do something after xmlRcpFinished
}
But this way of waiting and synchronizing get's ugly when the projects grows larger and I need to wait for many requests to finish.
So is this the only possible / best way? Or does someone knows a better solution?
My first shot to create blocking RPC calls would be:
// Little helper class:
class RPCResult<T>{
private final T result;
private final Exception ex;
private final long id;
public RPCResult( long id, T result, Exception ex ){
// TODO set fields
}
// TODO getters
public boolean hasError(){ return null != this.ex; }
}
public Object xmlRpcMethod() {
final BlockingQueue<RPCResult> pipe = new ArrayBlockingQueue<RPCResult>(1);
XMLRPCCallback listener = new XMLRPCCallback() {
public void onResponse(long id, final Object result) {
// Do something
pipe.put( new RPCResult<Object>(id, result, null) );
}
public void onError(long id, final XMLRPCException error) {
// Do something
pipe.put( new RPCResult<Object>(id, null, error) );
}
public void onServerError(long id, final XMLRPCServerException error) {
Log.e(TAG, error.getMessage());
pipe.put(new RPCResult<Object>(id, null, error));
}
};
XMLRPCClient client = new XMLRPCClient("<url>");
long id = client.callAsync(listener, "<method>");
RPCResult result = pipe.take(); // blocks until there is an element available
// TODO: catch and handle InterruptedException!
if( result.hasError() ) throw result.getError(); // Relay Exceptions - do not swallow them!
return result.getResult();
}
Client:
public void testMethod(){
Object result = xmlRpcMethod(); // blocks until result is available or throws exception
}
Next step would be to make a strongly typed version public T xmlRpcMethod().
try
{
if(ruleName.equalsIgnoreCase("RuleName"))
{
cu.accept(new ASTVisitor()
{
public boolean visit(MethodInvocation e)
{
if(rule.getConditions().verify(e, env, parentKeys, astParser, file, cu)) // throws ParseException
matches.add(getLinesPosition(cu, e));
return true;
}
});
}
// ...
}
catch(ParseException e)
{
throw AnotherException();
}
// ...
I need to catch thrown exception in the bottom catch, but I cannot overload method via throws construction. How to do with that, please advice? Thanks
Create custom exception, write try catch block in anonymous class and catch it in your catch block.
class CustomException extends Exception
{
//Parameterless Constructor
public CustomException () {}
//Constructor that accepts a message
public CustomException (String message)
{
super(message);
}
}
now
try
{
if(ruleName.equalsIgnoreCase("RuleName"))
{
cu.accept(new ASTVisitor()
{
try {
public boolean visit(MethodInvocation e)
{
if(rule.getConditions().verify(e, env, parentKeys, astParser, file, cu)) // throws ParseException
matches.add(getLinesPosition(cu, e));
return true;
}
catch(Exception e){
throw new CustomException();
}
});
}
// ...
}
catch(CustomException e)
{
throw AnotherException();
}
As suggested already, an unchecked exception could be used. Another option is to mutate a final variable. Eg:
final AtomicReference<Exception> exceptionRef = new AtomicReference<>();
SomeInterface anonymous = new SomeInterface() {
public void doStuff() {
try {
doSomethingExceptional();
} catch (Exception e) {
exceptionRef.set(e);
}
}
};
anonymous.doStuff();
if (exceptionRef.get() != null) {
throw exceptionRef.get();
}
What is advantage of locks over wait/notify?
Code is very similar.
private Object full = new Object();
private Object empty = new Object();
private Object data = null;
public static void main(String[] args) {
Test test = new Test();
new Thread(test.new Producer()).start();
new Thread(test.new Consumer()).start();
}
public void push(Object d) {
synchronized (full) {
while (data != null)
try {
full.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
data = d;
System.out.println("push");
synchronized (empty) {
if (data != null)
empty.notify();
}
}
public Object pop() {
synchronized (empty) {
while (data == null)
try {
empty.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Object o = data;
data = null;
System.out.println("pop");
synchronized (full) {
if (data == null)
full.notify();
}
return o;
}
class Producer implements Runnable {
public void run() {
while (true) {
push(new Object());
}
}
}
class Consumer implements Runnable {
public void run() {
while (true) {
pop();
}
}
}
and
private final ReentrantLock lock = new ReentrantLock();
private final Condition fullState = lock.newCondition();
private final Condition emptyState = lock.newCondition();
private Object data = null;
public static void main(String[] args) {
Test test = new Test();
new Thread(test.new Producer()).start();
new Thread(test.new Consumer()).start();
}
public void push(Object d) {
lock.lock();
try {
while (data != null)
try {
fullState.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
data = d;
System.out.println("push");
emptyState.signal();
} finally {
lock.unlock();
}
}
public Object pop() {
Object result;
lock.lock();
try {
while (data == null)
try {
emptyState.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
result = data;
data = null;
System.out.println("pop");
fullState.signal();
} finally {
lock.unlock();
}
return result;
}
class Producer implements Runnable {
public void run() {
while (true) {
push(new Object());
}
}
}
class Consumer implements Runnable {
public void run() {
while (true) {
pop();
}
}
}
Check out the JavaDoc for ReeentratLock and your question will be answered.
"A reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities."
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html