Override wait method in Java interface

I would like to use wait(int) as the method signature in a free API (used for http://www.jooq.org ). The goal is to be able to create SQL queries like this example:

 SELECT * FROM T_AUTHOR WHERE ROWNUM <= 1 FOR UPDATE OF FIRST_NAME, LAST_NAME WAIT 5 

The full FOR UPDATE clause syntax specification (at least for Oracle) can be seen here:

 FOR UPDATE [ OF [ [ schema. ] { table | view } . ] column [, [ [ schema. ] { table | view } . ] column]...] [ { NOWAIT | WAIT integer | SKIP LOCKED } ] 

http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/img_text/for_update_clause.htm

With jOOQ, I really want to stay close to SQL syntax. So I would like to be able to simulate the above SQL statement with a white jOOQ API as follows:

 Result<Record> result = create.select() .from(T_AUTHOR) .limit(1) .forUpdate() .of(FIRST_NAME, LAST_NAME) .wait(5) // Here the issue .fetch(); 

The fetch method is used to render the object underlying the API like SQL and run an SQL query on an Oracle database (or any other). The above can be legally specified in the interface:

 /** * A type that models a "step" in the creation of a query using the fluent API */ public interface SelectForUpdateWaitStep extends SelectFinalStep { // [...] /** * Add a "FOR UPDATE .. WAIT n" clause to the query */ SelectFinalStep wait(int seconds); // [...] } 

I have some doubts about this because there is a risk of collision with another method:

 public class Object { // [...] public final native void wait(long timeout) throws InterruptedException; // [...] } 

Thanks to the overload method ( int vs. long ), I can do this. But I am afraid that this may confuse my users and lead to errors. So that would be wrong:

  .forUpdate() .of(FIRST_NAME, LAST_NAME) .wait((long) 5) // This doesn't make sense .fetch(); // This doesn't compile 

So my questions are:

  • Is there any way to prevent calling / access to Object.wait(long) altoghether? I don’t think so because he declared final , but maybe someone knows a trick compiler or something else?
  • Do you have a better idea for my API design besides just renaming the method to something stupid like doWait(int) or wait(int) ?
+6
source share
4 answers

To do this, disable the Object method. And the main reason is that it has a nice name that will fit the purpose of the API.

At first, this contradicts the whole idea of ​​inheritance - as soon as you inherit from a class, all subclasses should expose the same non-personal fields and method. You can always override a method, unless (1) it is marked final and (2) it has an incompatible return type, both of which are true using the void wait(long) method.

Also, since every object is an Object in Java, everything should have a void wait(long) method, and there should be no way to hide / delete / disable / forward / redefine it. Assuming you could hide the void wait(long) method, how would you call it if you want to call it?

However, assuming you never need to call void wait(long) for your specific classes, there is always an approach to weaving source / byte code that AspectJ uses to make changes to. Java class bytecode based on specific handling rules. You can block every call to wait(long) and report an error / warning. More details here: http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations-decp.html

However , method-based point references are not possible even with AspectJ with skewed byte code. Most likely, this is not possible even when transcoding the source code, but it may be worth a try.

+2
source

Instead, you can try using the waitFor method, which determines both the time and the "condition" to wait. Implementation details will be hidden, but one possible implementation will be an attempt to immediately execute your action and execute a cycle until the specified condition is met with a corresponding pause between attempts.

Here's an example interface for Condition I use myself (as you can see, it should not be complicated):

 public interface Condition { public boolean met(); } 
+4
source

Hacking with the Java kernel for the sake of DSL is simply not a good idea.

Why not make your DSL more expressive?

What does wait (int n) mean? wait N milliseconds, seconds, minutes?

The best signature would be:

wait (long duration, java.util.concurrent.TimeUnit) {...}

which is better read, for example:

wait (30, TimeUnit.MILLISECONDS)

+3
source

void wait(long) is part of the contract offered by Object , and therefore should not be changed. Imagine someone is saving your object and trying to use it for the wait/notify thread logic. Thus, a complete change in his logic simply plays against the rules. So you have to come up with a different name.

On the other hand, it seems that forUpdate taking a parameter indicating that the timeout will match the count. You could just add another version of forUpdate in addition to the existing one.

+3
source

Source: https://habr.com/ru/post/890826/


All Articles