Kotlin: "synchronized" makes compiler not to be sure about the initialization of a variable - thread-safety

Let's imagine the next piece of Kotlin code that performs some query to a database by means a JDBC connector:
var results : ResultSet
preparedStatement.clearParameters()
preparedStatement.setInt(1,value1);
preparedStatement.setInt(2,value2)
results = preparedStatement.executeQuery()
while(results.next()) {
// parse results
}
that compiles without problems. However, when I try to add thread safety to the access to the preparedStatement:
var results : ResultSet
synchronized(preparedStatement) {
preparedStatement.clearParameters()
preparedStatement.setInt(1,value1);
preparedStatement.setInt(2,value2)
results = preparedStatement.executeQuery()
}
while(results.next()) {
// parse results
}
... I got a "Variable 'results' must be initialized". It seems the synchronized block acts as a conditional block, but you can be sure that it will be executed once, before the while block.
I have implemented this same block in Java and I don't get the error. Is this a design/implementation error of Kotlin? Or does it have a good reason to behave like that?

synchronized is just an inline function and compiler doesn't know if lambda will be executed once, or even executed at all. Idiomatic way is to return value from lambda and assign it to the local:
val results =
synchronized(preparedStatement) {
preparedStatement.clearParameters()
preparedStatement.setInt(1,value1);
preparedStatement.setInt(2,value2)
preparedStatement.executeQuery()
}

Related

Multiplatform runBlocking coroutine tests fail if last assertion doesn't have a Unit return type

I'm testing my coroutine functions in my Kotlin Multiplatform project. I've mocked out the implementation behind them, so no actual await occurs during tests.
Consider the following test, curated from the test README:
#Test fun testAsyncFunction() = runBlocking {
val result: List<myClass> = myService.someSuspendFunction()
assertEquals(result.first()?.name, "name")
assertNotNull(result.first()?.someRequiredValue)
}
The second assertion has a return type of T, which causes its result to be returned to the runBlocking function, throwing the following error:
Invalid test class 'com.example.shared.core.service.ExampleTests':
1. Method testAsyncFunction() should be void
I've found 2 solutions to this, either I can swap the two assertions around (assertEquals has a Unit return type, thus no issues), or write val ignored = assertNotNull(result.first()?.someRequiredValue). However neither of these two solutions are ideal, as I'll either have extraneous code that my IDE is warning me to remove, or my assertions are out of order.
What is the best solution to this issue?
The problem is that the method is inferring the return type from runBlocking, which returns value from the inner suspending function.
You can force it to generate a void return type by specifying the return type : Unit explicitly rather than rely on the inferred value.

linter err113: do not define dynamic errors, use wrapped static errors instead

I am using err113 as part of golangci-lint.
It is complaining about ...
foo_test.go:55:61: err113: do not define dynamic errors, use wrapped static errors instead: "errors.New(\"repo gave err\")" (goerr113)
repoMock.EXPECT().Save(gomock.Eq(&foooBarBar)).Return(nil, errors.New("repo gave err")),
^
foo_test.go:22:42: err113: do not define dynamic errors, use wrapped static errors instead: "errors.New(\"oops\")" (goerr113)
repoMock.EXPECT().FindAll().Return(nil, errors.New("oops"))
^
What is best way to fix this ?
Quoting https://github.com/Djarvur/go-err113
Also, any call of errors.New() and fmt.Errorf() methods are reported
except the calls used to initialise package-level variables and the
fmt.Errorf() calls wrapping the other errors.
I am trying to get a idiomatic example for this.
Declare a package-level variables as suggested:
var repoGaveErr = errors.New("repo gave err")
func someFunc() {
repoMock.EXPECT().Save(gomock.Eq(&foooBarBar)).Return(nil, repoGaveErr)
}
Every call to errors.New allocates a new unique error value. The application creates a single value representing the error by declaring the package-level variable.
There are two motivations for the single value:
The application can compare values for equality to check for a specific error condition.
Reduce memory allocations (although probably not a big deal in practice)
The value io.EOF is a canonical example.
Since GO 1.13 you can define a new error type, wrap it and use it.
for example, if you want to return an "operation not permitted" + the operation.
you need to implement something like
var OperationNotPermit = errors.New("operation not permitted")
func OperationNotFoundError(op string) error {
return fmt.Errorf("OperationNotPermit %w : %s", OperationNotPermit, op)
}
then in your code, when you want to return the error,
return nil, OperationNotFoundError(Op)
Let's back to question case:
first, define the custom error and the wapper
var repoError = errors.New("repositoryError")
func RepositoryError(msg string) error {
return fmt.Errorf("%w: %s", repoError,msg)
}
then in your code,
repoMock.EXPECT().Save(gomock.Eq(&foooBarBar)).Return(nil, RepositoryError("YOUR CUSTOM ERROR MESSAGE"))
Since it hasn't been said before, you probably don't need to define package level errors for tests. Given the idea is to wrap errors so they can be compared and unwrapped in the caller, returning a dynamic error in a test is fine as long as the purposes of your test are served.

AtomicBoolean parallel version does not work - but Agent version does

I have a method where I tried to parallelise the calc using GPARS and calculate an aggregate boolean 'And' result across the calls. This method is wrapped as a #ActiveObject which will deliver the result as a dataflow - the code below has the original approach where I tried to store the aggregate using AtomicBoolean to protect it.
This didn't work (sometimes my tests would pass others they would fail) on the calculated 'end truth'. To fix this I changed from AtomicBoolean to a Agent(boolean) approach and I think it's 'fixed' it - at least my spock tests are continuously succeeding.
Where was my logic flawed trying to use AtomicBoolean to build the final result? It felt like it should work - but doesn't and I don't understand why.
Method below - I've put the original version, and the corrected version below
#ActiveMethod
def evaluateAllAsync () {
AtomicBoolean result = new AtomicBoolean(true)
GParsPool.withPool {
// do as parallel
conditions.eachParallel { condition ->
println "evalAllAsync-parallel intermediate result start value is ${result.get()} and condition with expression ${condition.expression} evaluated to ${condition.evaluate()}"
result.getAndSet(result.get() && condition.evaluate())
println "recalc bool value is now ${result.get()}"
}
}
println "evalAllAsync-parallel final result value is ${result.get()}"
result.get()
}
Fixed issue by using Agent form like this
#ActiveMethod
def evaluateAllAsync () {
def result = new Agent (true)
GParsPool.withPool {
// do as parallel
conditions.eachParallel { condition ->
println "evalAllAsync-parallel intermediate result start value is ${result.val} and condition with expression ${condition.expression} evaluated to ${condition.evaluate()}"
result << { def res = it && condition.evaluate(); println "start> $it and finish> $res"; updateValue(res)}
println "recalc bool value is now ${result.val}"
}
}
println "evalAllAsync-parallel final result value is ${result.val}"
result.val
}
I put debug println in here just so I could see what code was doing.
The version with the Agent to protect the bool aggregate value appears to be working.
Why doesn't the Atomic Boolean work?
Well, this is an issue in how you use AtomicBoolean. You always overwrite by force (getAndSet()) the value stored in it and ignore the possibility that other threads could have changed it while the current thread is busy 'evaluating'.
You perhaps wanted to use the compareAndSet() method instead:
def valueToUse = result.get()
result.compareAndSet(valueToUse, valueToUse && condition.evaluate())

Q Promises - Create a dynamic promise chain then trigger it

I am wondering if there's a way to create a promise chain that I can build based on a series of if statements and somehow trigger it at the end. For example:
// Get response from some call
callback = (response) {
var chain = Q(response.userData)
if (!response.connected) {
chain = chain.then(connectUser)
}
if (!response.exists) {
chain = chain.then(addUser)
}
// etc...
// Finally somehow trigger the chain
chain.trigger().then(successCallback, failCallback)
}
A promise represents an operation that has already started. You can't trigger() a promise chain, since the promise chain is already running.
While you can get around this by creating a deferred and then queuing around it and eventually resolving it later - this is not optimal. If you drop the .trigger from the last line though, I suspect your task will work as expected - the only difference is that it will queue the operations and start them rather than wait:
var q = Q();
if(false){
q = q.then(function(el){ return Q.delay(1000,"Hello");
} else {
q = q.then(function(el){ return Q.delay(1000,"Hi");
}
q.then(function(res){
console.log(res); // logs "Hi"
});
The key points here are:
A promise represents an already started operation.
You can append .then handlers to a promise even after it resolved and it will still execute predictably.
Good luck, and happy coding
As Benjamin says ...
... but you might also like to consider something slightly different. Try turning the code inside-out; build the then chain unconditionally and perform the tests inside the .then() callbacks.
function foo(response) {
return = Q().then(function() {
return (response.connected) ? null : connectUser(response.userData);
}).then(function() {
return (response.exists) ? null : addUser(response.userData);//assuming addUser() accepts response.userData
});
}
I think you will get away with returning nulls - if null doesn't work, then try Q() (in two places).
If my assumption about what is passed to addUser() is correct, then you don't need to worry about passing data down the chain - response remains available in the closure formed by the outer function. If this assumption is incorrect, then no worries - simply arrange for connectUser to return whatever is necessary and pick it up in the second .then.
I would regard this approach to be more elegant than conditional chain building, even though it is less efficient. That said, you are unlikely ever to notice the difference.

Cast Exception when performing LINQ on IEnumerable

Let's say I have two classes,
class A
{
}
class B : A
{
}
I have a method which accepts a parameter foo of type IEnumerable<A>;
void AMethod(IEnumerable<A> foo)
{
}
but instead pass in a value of type IEnumerable<B>.
AMethod(new[] { new B() });
This compiles and executes, though at execution foo has been implicitly cast to IEnumerable<B>. Now let's say my IEnumerable<B> contains objects of type A (I don't believe it matters whether they're mixed or all the same). When I call foo.Any() I get an exception:
Unable to cast object of type 'A' to type 'B'
I understand that I can't convert a base class to a subclass, but that's not what I'm trying to do (in fact at this point in execution, I don't even care what type it is). I guess LINQ is inherently trying to make this conversion, probably based on the fact that foo is type IEnumerable<B>. So, it seems as though I need to write two separate methods, one which handles IEnumerable<A> and one which handles IEnumerable<B>. I don't understand why I would need to do this. Any thoughts?
EDIT:
There's some dynamic casting and transformation going on that manages to spit out a IEnumerable<B> populated with 'A's, which until now I thought was impossible too. I'll do my best to translate what's happening leading up to this method call:
protected void SetDynamicData(dynamic data)
{
_data = data;
IsB = typeof(IBInterface).IsAssignableFrom(_data.DataType);
}
...
var foo = IsB ? _data.Cast<B>() : data.Cast<A>();
return BuildJqGridData<A, B, int>(gridModel, foo);
An IEnumerable<B> cannot contain objects of type A because and A is not a B.
I can write this code,
IEnumerable<B> dodgy = (new[] { new A() }).Cast<B>();
It will compile, despite being obviously wrong. The compiler assumes I know what I'm doing. Remember that no item in the IEnumerable sequence has yet been evaluated.
When I write code that evaluates a member of dodgy I get exception because an A is not a B and does not support casting to B.
I can write
IEnumerable<A> fine = new[] { new B() };
no cast is required and everything works fine because a B is an A.
If I do,
var hungrilyDodgy = (new[] { new A() }).Cast<B>().ToList();
the Tolist() will force enumeration and evaluation of the IEnumerable, therefore the exception will be thrown much sooner.

Resources