Need help with callbacks and anonymous classes in Java - java

I am using some third party library to connect to a server via async protocol and get response back. For example method to get userid by username looks like this:
public int getUserid(String username) {
int userid = 0;
connection.call("getUserid", new Responder() {
public void onResult(final int result) {
System.out.println("userid: " + result);
//how to assign received value to userid and return it?
}
}, username);
//wait for response
while (userid == 0) {
try{
Thread.sleep(100);
} catch (Exception e) {}
}
return userid;
}
The problem is I can't assign returned "result" from server response to "userid" variable from the method (in order to return it after). How to solve this? I probably can assign it to some class variable rather than method variable but I want to keep it within method scope so I don't have to deal with concurrency issues.
Thanks.

If I understand your question correctly, you're asking how you can write a variable from inside an anonymous class.
Anonymous classes can only access final variables, and can't directly "write" them.
A straightforward solution that is "good enough" is to create sort of a ValueBox class with a single value field and a getter and setter. You can then instantiate a new one in the function as a final variable, and have your anonymous class access it. The anonymous class will use its getter and setter to write/read.
The fact that the variable is final just means that you can't aim the reference anywhere else, but you can still change the contents of the referred object from either function.
The bigger problem you are going to have is in waiting until the callback has been called. This sort of wait-sleep might be good enough, but you may want to consider timeouts, threads, etc, depending on what you're trying to achieve.
In addition, this all assumes that you are never going to call this twice on the connection. Otherwise, you need to provide more info to us on your synchronization model.
Here's some sample code:
public int getUserid(String username) {
final ValueBox<Integer> userid = new ValueBox<Integer>();
connection.call("getUserid", new Responder() {
public void onResult(final int result) {
System.out.println("userid: " + result);
userId.setValue(result);
//how to assign received value to userid and return it?
}
}, username);
//wait for response
while (userid.isEmpty()) {
try{
Thread.sleep(100);
} catch (Exception e) {}
}
return userid.getValue();
}

The simplest change is to use something like java.util.concurrent.SynchronousQueue. But possibly you want to provide an event driven interface yourself.

Related

Java: Use reflection or store instance objects in list?

how are you? I'm trying to do some dynamic method calls to get sql strings on various objects in Java (Android), but i'm stuck with some questions about performance and stability.
Context Example: Repository class onCreate method get all entity objects (tables) and call a method (getCreateTable for example) to get a sql string to execute.
Sure i can explicit call class by class caling each method, but i have other calls like "dropTables", "truncateTables" and etc, and i do not want to be repeating the same structure all the time.
public void CreateTables() {
execute(Entity1.getCreateTable());
execute(Entity2.getCreateTable());
execute(Entity3.getCreateTable());
[..]
execute(Entity50.getCreateTable());
}
public void DropTables() {
execute(Entity1.getDropTable());
execute(Entity2.getDropTable());
execute(Entity3.getDropTable());
[..]
execute(Entity50.getDropTable());
}
Until now i know i can do that in 3 diferent ways.
1) Using reflection (currently in use): Basicaly, i store all the objects class in a list, and then use the reflection to call the desired static method.But i know that reflection not always should be the first choice.
private final List<Class> entityList = new ArrayList<Class>() {
{
add(Entity1.class);
add(Entity2.class);
add(Entity3.class);
}
};
public void createTables() {
/* get all query strings */
List<String> queryList = getQueryList("createTable");
try {
for (String query : queryList) {
execute(query);
}
} catch (SQLException e) {
[...]
}
}
private List<String> getQueryList(String methodName) {
List<String> queryList = new ArrayList<>();
for (Class<?> objectClass : entityList) {
try {
Method[] ms = objectClass.getMethods();
for (Method me : ms) {
if (me.getName().equals(methodName)) {
String query = (String) me.invoke(null);
if (query != null && query.length() > 0) {
queryList.add((String) me.invoke(null));
}
break;
}
}
} catch (Exception e) {
[...]
}
}
return queryList;
}
2) Storing object instance in list: I can have a list with the objects instanced and then cast then into abstract parent class (or interface) and call the methods to get the sql string. In this case, i don't know if is a good practice to keep an list of instanced objects in memory, maybe this could be worst than use reflection depending on list size.
private final List<BaseEntity> entityList = new ArrayList<BaseEntity>() {
{
add(new Entity1(context));
add(new Entity2(context));
add(new Entity3(context));
}
};
public void createTables() {
for (BaseEntity entity : entityList) {
try {
execute(entity.getCreateTable());
} catch (Exception e) {
[...]
}
}
}
3) Storing all the strings into JSON object: I don't tested that one yet, but i'm sure with should work. I can call an "init" method to iterate over all objects and create that JSON object/array with all the sql strings (drop, create, truncate and etc).
I really appreciate if you share with me what you think about these approaches (pros and cons) or another better solution.
As pointed out in the comments, it was a clarly a bad design (it's an old project that i'm refactoring). So i decided to get away from reflection and spend some time to redesign the code itself.
I created an base super class to handle all similiar methods and let the entities/models implement only the required individual rules, so DB access is stored in only one class as a Singleton. It's far better to use interface polymorphism.
In this way, the db class handle the dinamic SQL generation to avoid repeating the same code everywhere and re-use/recycle the list of instances to improve performance.
Obs. 1: Reflection throw down performance and usually let debbuging harder. Sure it can save some time as it is fast to implement, but will disable most of the IDE features, which makes it worthless in most cases.
Obs. 2: Keeping a list of DB instances active should never be done either. It's never a good idea to have many instances access database simultaneously, it can cause DB to lock and reproduce unexpectad issues.
Obs. 3: That JSON thing... forget about it. I'm sorry to suggest something so ugly.

Invoke Java object constant using a variable

I'm very new to Java so it makes it hard for me to explain what I'm trying to do.
I have an abstract class that invokes several object constants like this:
public abstract class Enchantment implements Keyed {
/**
* Provides protection against environmental damage
*/
public static final Enchantment PROTECTION_ENVIRONMENTAL = new EnchantmentWrapper("protection");
In a different file I can access this perfectly fine with Enchantment value = Enchantment.PROTECTION_ENVIRONMENTAL;
However, I'm trying to use a string variable for this instead. Something like this:
String str = "PROTECTION_ENVIRONMENTAL";
Enchantment value = Enchantment.str;
Obviously that won't work. So I did a bunch of research and learned I need to use reflection for this. Using this source code's docs I figured I was looking for field data. So I tried both:
Field fld = Enchantment.class.getField("PROTECTION_ENVIRONMENTAL");
Field fld = Enchantment.class.getDeclaredField("PROTECTION_ENVIRONMENTAL");
But these returned me a NoSuchFieldException. As I was on it, I've tried both getMethod() and getDeclaredMethod() just as well equally with no luck.
I'm now at the point that these are probably "object constants"? I'm not sure how to call them. But I'm definitely at a loss on how to get this to work now and after everything I've tried myself, I figured it was time to ask for some help here.
That one comment is spot on: you absolutely do not use reflection here.
There are only two valid reasons to use reflection:
you are creating a framework that has to deal with classes it doesn't know about
you have for some other reason to deal with classes you don't know about at compile time
But your code perfectly knows about that Enchantment class, its capabilities, and so on. Therefore reflection is the wrong approach. You figured it yourself: it is damn hard to get right, and damn right to get it wrong in some subtle ways. And when you get it wrong, it always blows up at runtime. Reflection code compiling means nothing. It always waits for you to run it to throw up in your face.
So to answer your question by not answering it: use a Map. Like:
Map<String, Enchantment> enchantmentsByConstantName = new HashMap<>();
enchantmentsByConstantName.put("PROTECTION_ENVIRONMENTAL", PROTECTION_ENVIRONMENTAL);
Alternatively, these constants could go into an enum, as outlined in the other answer, but in a sightly different way:
enum EnchantmentHolder {
PROTECTION_ENVIRONMENTAL(new EnchantmentWrapper("protection")),
ANOTHER_ENCHANTMENT(...)
A_THIRD_ENCHANTMENT(...)
...;
private Enchantment enchantment;
private EnchantmentHolder(Enchantment enchantment) {
this.entchantment = entchantment;
}
public Enchantment getEntchantment() { return entchantment; }
You may want to look into enumerations if you know they're going to be constant values;
public enum Enchantment {
PROTECTION_ENVIRONMENTAL {
public void cast() {
// do enum-specific stuff here
}
},
ANOTHER_ENCHANTMENT {
public void cast() {
// do enum-specific stuff here
}
},
A_THIRD_ENCHANTMENT{
public void cast() {
// do enum-specific stuff here
}
};
public abstract void cast();
}
enums can be treated like classes and have methods and properties. You can also convert to and from strings Enchantment.valueOf("PROTECTION_ENVIRONMENTAL") but that's generally if you are reading from a configuration file - in code you'd reference the value directly.
Once you have the Field, you need to call Field.get(Object) with an instance (in this case the class). Something like,
Class<?> cls = Enchantment.class;
try {
Field f = cls.getField("PROTECTION_ENVIRONMENTAL");
System.out.println(f.get(cls));
} catch (Exception e) {
e.printStackTrace();
}
Since you want the Enchantment, you could then test that the instance you get is assignable to Enchantment. Something like,
Class<? extends Enchantment> cls = Enchantment.class;
try {
Field f = cls.getField("PROTECTION_ENVIRONMENTAL");
Object obj = f.get(cls);
if (cls.isAssignableFrom(obj.getClass())) {
Enchantment e = cls.cast(obj);
System.out.println(e);
}
} catch (Exception e) {
e.printStackTrace();
}
But the enum approach is better.

How can I prevent invoking a static method on an instance of my class? [duplicate]

This question already has answers here:
Can we call a static method with a null object in Java? If so, how?
(4 answers)
Closed 4 years ago.
I have the following class, which is used for controlling some debugging and beta testing options in various places in my Android app. It just contains some flags and some logic to (de)serialize it to/from JSON.
public class DevConfiguration {
public boolean dontSendSMS;
public static String toJsonString(DevConfiguration devConfiguration) {
JSONObject json = new JSONObject();
if( devConfiguration != null ) {
try {
json.put("dontSendSMS", devConfiguration.dontSendSMS);
} catch (JSONException e) {
e.printStackTrace();
}
}
return json.toString();
}
public static DevConfiguration fromJsonString(String jsonString) {
if( jsonString.isEmpty() )
return null;
DevConfiguration result = new DevConfiguration();
try {
JSONObject jsonObj = new JSONObject(jsonString);
result.dontSendSMS = jsonObj.optBoolean("dontSendSMS", false);
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
}
Now, in one of my services I receive a serialized DevConfiguration object in an Intent, and might later pass it on to another service:
serviceIntent.putExtra("dev_conf", DevConfiguration.toJsonString(mDevConfiguration));
I choose to make the toJsonString() method static, so that I don't risk invoking it on a null instance. However, it's still possible to make a mistake somewhere and invoking the static method on an instance - potentially a null instance!
mDevConfiguration.toJsonString(mDevConfiguration);
There is a Lint warning in Android Studio, but still it's a potential NullPointerException bug waiting to happen. I thought it might be possible to hide it by defining a similar private method but with a different signature
/** Hide instance implementation **/
private String toJsonString(Object o){ return ""; }
but of course calling it with a DevConfiguration parameter will invoke the static method anyway, and the IDE doesn't give any more warnings than before either.
Is there any way to "hide" the static method from instance variables?
EDIT
Comments make it clear that invoking a static method on a null instance is perfectly legal. However, the question is not "How do I prevent a NullPointerException when invoking a static method on a null instance?", but the more general "How can I prevent invoking a static method on an instance of my class?".
In other words - is there any way to prevent the compiler from compiling if one accidentally tries to invoke a static method on an instance?
Calling a static method on a variable with null value will not raise NullPointerException. Following code will print 42 even though variable i is null.
public class Test {
public static void main(String... args) {
Integer i = null;
System.out.println(i.parseInt("42"));
}
}
When calling static methods by variable, what really matters is the declared type of the variable and not the referenced type of its value. This is related to the fact that static methods in java are not polymorphic.
„How can I prevent invoking a static method on an instance of my class?"
Calling static methods by variable is just a regular language feature defined in the Java spec. I’d be surprised if there were any method to suppress it in general.
If I had to do it for a selected class, I would probably migrate static methods to a separate „companion” utility (as described in another answer).
But having such static (factory) methods in your class is a perfectly fine idiom (see for example: Joshua Bloch, „Effective Java”, Item 1: Consider static factory methods instead of constructors). I wouldn’t easily give up on it.
I see a few ways you could do this:
Use a Utils class:
public class Utils {
public static String toJsonString(DevConfiguration devConfiguration) {
JSONObject json = new JSONObject();
if( devConfiguration != null ) {
try {
json.put("dontSendSMS", devConfiguration.dontSendSMS);
} catch (JSONException e) {
e.printStackTrace();
}
}
return json.toString();
}
public static DevConfiguration fromJsonString(String jsonString) {
if( jsonString.isEmpty() )
return null;
DevConfiguration result = new DevConfiguration();
try {
JSONObject jsonObj = new JSONObject(jsonString);
result.dontSendSMS = jsonObj.optBoolean("dontSendSMS", false);
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
}
Now you can just makes calls to Utils.method() and avoid confusion.
Use Kotlin
Kotlin actually makes it really hard (if not impossible) to call a static method on a dynamic receiver. It won't show in the method suggestions, and will underline in red if you type it manually. It might not even compile, although I haven't gotten that far.
Kotlin also has built-in null protection: instance?.method(). The ? means method() just won't execute if instance is null.
Just don't call a static method on a dynamic receiver. If you do it by accident, go back and fix it. You shouldn't be relying on Java to work around your syntax errors for you.
Finally, why even do this? I highly doubt mDevConfiguration is ever null, unless you initialize it in a really weird spot. If it is, you may want to look at reorganizing your code. Because, again, you shouldn't be relying on Java to work around your syntax errors for you. Also, if it is null, it won't throw an NPE, at least in Java, since it doesn't need a dynamic receiver to run (this is probably different in Kotlin).
It's up to you to make code that works as it should, and implement the proper null checks, error handling, etc. If you miss something, it's no big deal; that's why you test your code and fix the crashes and bugs you catch before you release it. Anything you don't catch will be reported by the Google Play Console (if you publish there) or Firebase (if you implement that) or your users.
Sorry if the above sounds harsh, but I'm really having trouble seeing why you'd want to do this instead of just checking your code.
If you really want to keep this structure, at least make the constructor for DevConfiguration private:
public class DevConfiguration {
//...
private DevConfiguration() {}
//...
}
That way, only the static methods inside it can create an instance.

AWS Java Lambda local variables vs object variables

I am trying to find answer to a very specific question. Trying to go through documentation but so far no luck.
Imagine this piece of code
#Override
public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
Request request = parseRequest(input);
List<String> validationErrors = validate(request);
if (validationErrors.size() == 0){
ordersManager.getOrderStatusForStore(orderId, storeId);
} else {
generateBadRequestResponse(output, "Invalid Request", null);
}
}
private List<String> validate(Request request) {
orderId = request.getPathParameters().get(PATH_PARAM_ORDER_ID);
programId = request.getPathParameters().get(PATH_PARAM_STORE_ID);
return new ArrayList<>();
}
Here, I am storing orderId and storeId in field variables. Is this okay? I am not sure if AWS will cache this function and hence cache the field variables or would it initiate a new Java object for every request. If its a new object, then storing in field variable is fine but not sure.
AWS will spin up a JVM and instantiate an instance of your code on the first request. AWS has an undocumented spin down time, where if you do not invoke your Lambda again within this time limit, it will shut down the JVM. You will notice these initial requests can take significantly longer but once your function is "warmed up", then it will be much quicker.
So to directly answer your question, your instance will be reused if the next request comes in quick enough. Otherwise, a new instance will be stood up.
A simple Lambda function that can illustrate this point:
/**
* A Lambda handler to see where this runs and when instances are reused.
*/
public class LambdaStatus {
private String hostname;
private AtomicLong counter;
public LambdaStatus() throws UnknownHostException {
this.counter = new AtomicLong(0L);
this.hostname = InetAddress.getLocalHost().getCanonicalHostName();
}
public void handle(Context context) {
counter.getAndIncrement();
context.getLogger().log("hostname=" + hostname + ",counter=" + counter.get());
}
}
Logs from invoking the above.
22:49:20 hostname=ip-10-12-169-156.ec2.internal,counter=1
22:49:27 hostname=ip-10-12-169-156.ec2.internal,counter=2
22:49:39 hostname=ip-10-12-169-156.ec2.internal,counter=3
01:19:05 hostname=ip-10-33-101-18.ec2.internal,counter=1
Strongly not recommended.
Multiple invocations may use the same Lambda function instance and this will break your current functionality.
You need to ensure your instance variables are thread safe and can be accessed by multiple threads when it comes to Lambda. Limit your instance variable writes to initialization - once only.

What is the best practice to set parameters to object and avoid duplicated code?

I'm working in a project that have some entities, and to set the entities attributes, we have a lot of code like this:
public void recordLogFile(int fileSize, int fileHeight, Long idFile) {
try {
LogFileEntity logEntity = new LogFileEntity();
logEntity.setFileSize(fileSize);
logEntity.setFileHeight(fileHeight);
logEntity.setFile(FileEntity.find(idFile));
logEntity.setStatus(LogStatus.SUCESS);
logEntity.setType(LogType.NORMAL);
logEntity.persist();
} catch (Exception e) {
some log code
}
}
There are a lot of classes that need to persist the log file entity, but in some cases we have different values on attributes. For example LogStatus.FAIL LogType.OLD, and we have a repeated piece of code only changing the value.
What is the best approach to make this better??
Thanks !!!
You can do a couple of things. The simplest thing is to create objects that are built with default values, and provide constructors to fill out the rest. For example, you have this class LogFileEntity which appears to have 5 attributes: fileSize, fileHeight, file, logStatus, and logType. Let us assume that LogStatus.SUCESS and LogType.NORMAL are default values. If you set these values in the LogFileEntity, the client will not have to set them all the time. Your class constructor could look something like this:
public LogFileEntity()
{
logStatus = LogStatus.SUCESS;
logType = LogType.NORMAL;
// Maybe set other default values
}
That said, the best you can do is make use of the Factory Design Pattern to implement this.
The simplest resolution to your immediate issue is to add an overloaded method that takes the additional parameters:
public void recordLogFile(int fileSize, int fileHeight, Long idFile) {
recordLogFile(fileSize, fileHeight, idFile, LogStatus.SUCESS, LogType.NORMAL);
}
public void recordLogFile(int fileSize, int fileHeight, Long idFile,
LogStatus status, LogType type) {
try {
LogFileEntity logEntity = new LogFileEntity();
logEntity.setFileSize(fileSize);
logEntity.setFileHeight(fileHeight);
logEntity.setFile(FileEntity.find(idFile));
logEntity.setStatus(status);
logEntity.setType(type);
logEntity.persist();
} catch (Exception e) {
// some log code
}
}

Categories