I have a function which handle retry logic for given function. Inside that function I want to print a debug log with given function name and possibly the class name (Of course caller can pass that information) but I want to know how to get those values without call.
My retry method is below, now I get the methodName as an argument, can I just take it from fn ?
def retry[T](attempts: Int, max: Int, operation: String)(fn: => T): T = {
try {
fn
} catch {
case e : Throwable => {
if (attempts < max) {
val retryAttempt = attempts + 1
Thread.sleep((scala.math.pow(2, retryAttempt) * 2000).toLong)
logger.debug(s"Retrying operation: $operation retryCount $retryAttempt")
retry(retryAttempt, max, operation)(fn)
} else {
throw e
}
}
}
}
Related
I am writing a scala month function that will return an Integer month number when called. This function is passing the compilation stage but throwing error while being called at run time.
import java.time.Month
import java.util.Calendar
object Test {
val FINAL_MONTH_NBR = 12
def main(args: Array[String])
{
month()
}
def month(): Int = {
val month = System.getProperty("month")
if(month == null) {
Calendar.getInstance().get(Calendar.MONTH)
}
else {
val monthValue = Month.valueOf(month)
if (monthValue == Month.JANUARY) {
FINAL_MONTH_NBR
}
else {
monthValue.getValue - 1
}
}
}
}
This is throwing error: java.lang.IllegalArgumentException: No enum constant java.time.Month.UNDEFINED The error is at below line
val monthValue = Month.valueOf(month)
can anybody suggest how to fix this.
I would guess this line is the underlying problem:
val month = System.getProperty("month")
You check whether the value is null and handle that case, but what if the system property is foo? When you call Month.valueOf(month) there is no foo on the object, so you get the error.
Scala has useful features for working with exceptions which can help here. Consider the following:
def month(): Int = {
val monthSystem: Either[Exception, Int] = try Right(System.getProperty("month").toInt) catch {
case e: Exception => Left(e)
}
val month: Either[Exception, Month] = monthSystem.map(m => Month.valueOf(m.toString))
val mSafe: Int = month fold(
(ex: Exception) => {
// see what went wrong
println(ex.getMessage)
// default case
Calendar.getInstance().get(Calendar.MONTH)
},
(m: Month) => m.getValue
)
if (mSafe == Month.JANUARY.getValue) FINAL_MONTH_NBR else mSafe - 1
}
Wrapping the system call in an Either let's us capture the result if all is well, and the exception if something goes wrong. We can then use map like normal. It is 'right biased' so when we map over the results it just applies the function as if there were a value present, even if an exception were thrown. Normally you would probably just string all those calls together in Scala, but I've broken them out so it's clearer to follow.
Once we have a possible value in the form we want we call fold to handle both cases. fold takes two functions, one to handle the possible Exception case, and one to handle the possible Month case. Here we can use the first method to log any problems and return a default value.
Use a list of month names instead and set it if it doesn't belongs to list as given below.
def month(): Int = {
val month = System.getProperty("month")
val monthList = List("JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER")
if(!monthList.contains(month)) {
Calendar.getInstance().get(Calendar.MONTH)
}
else {
val monthValue = Month.valueOf(month)
if (monthValue == Month.JANUARY) {
FINAL_MONTH_NBR
}
else {
monthValue.getValue - 1
}
}
}
Don't forget to select it if it does your problem.
I'm attempting to perform some retry logic with Scala. For the sake of providing a MRE, I have replaced the exception-throwing object with Y. When running X.main. I expect to see this print two failure messages, then one success message, but it appears that the return statement is effectively acting as a no-op, and I'm seeing 3 success messages.
I realize this isn't idiomatic Scala and there are plenty of other ways to accomplish this, but is there no way to return from within a for loop in Scala? If not, why is that?
object X {
def main(args : Array[String]) : Unit = {
val y = new Y()
for ( i <- 1 to 5 ) {
try {
y.doSomething()
return
} catch {
case e : Throwable =>
if ( i == 5 ) {
throw e
}
}
}
}
}
class Y {
var counter = 0
def doSomething() : Unit = {
if ( counter < 2 ) {
println("Tried to do something, but failed")
counter += 1
throw new RuntimeException
}
println("Did something")
}
}
return is even more weird than you thought, not just "non-idiomatic".
It actually throws an exception. Your catch clause catches and swallows it. That's why it "acts as no-op".
Don't do this. Please.
But, if you insist, do, at least catch { case NonFatal(e) => instead as suggested in the comment - that would let through the exceptions thrown by return.
I have a controller that runs some code, I wrap some code in try/catch and wish to break the controller run during catch and return the error.
It does not return, How can I wrap my response in action function as required?
Sample:
def updateProduct(productId : String, lang : String, t : String) = Action {
request =>
request.body.asJson.map {
json =>
var product : Product = null
try {
product = json.as[Product]
}
catch {
case ex : Exception => {
val errorResponse : ErrorResponse[String] = ErrorResponse(ErrorCode.InvalidParameters, ex.getMessage, 500)
return InternalServerError(Json.toJson(errorResponse)) //Does not stop,
}
}
val response = productService.updateProduct(UpdateProductRequest(lang, t, productId, product))
if (response.isError) {
InternalServerError(Json.toJson(response))
}
else {
Ok(Json.toJson(response))
}
}.getOrElse {
Logger.warn("Bad json:" + request.body.asText.getOrElse("No data in body"))
var errorResponse : ErrorResponse[String] = ErrorResponse(ErrorCode.GeneralError, "Error processing request", 500)
errorResponse.addMessage("No data in body")
Ok(Json.toJson(errorResponse))
}
}
I get an error:
method `updateProduct` has return `statement`; needs result type
When you use return you must, as it says, use an explicit return type. Scala will not infer it for you.
So, for example:
def fails(i: Int) = return (i+1) // Doesn't compile
def works(i: Int): Int = return (i+1) // Does
I am not sure what the common supertype of Ok and InternalServerError is, but that would be what you're after. If it's an unhelpful type like AnyRef (i.e. Object), using Either or the equivalent might be a good idea (i.e. Left(InternalServerError/*...*/), Right(Ok/*...*/)).
I have the below requirement where I am checking whether a value is greater than 10 or not and based on that I will break, otherwise I will return a String. Below is my code:
import scala.util.control.Breaks._
class BreakInScala {
val breakException = new RuntimeException("Break happened")
def break = throw breakException
def callMyFunc(x: Int): String = breakable(myFunc(x))
def myFunc(x: Int): String = {
if (x > 10) {
"I am fine"
} else {
break
}
}
}
Now what is the happening is that I am getting the error message saying "type mismatch; found : Unit required: String" The reason is :
def breakable(op: => Unit)
But then how I will write a function which can return value as well as break if required?
The Scala compiler can evaluate that a branch throws an exception and not use it to form a minimum bound for the return type, but not if you move the throwing code out in a method: since it can be overridden, the compiler cannot be sure it will actually never return.
Your usage of the Break constructs seems confused: it already provides a break method, there is no need to provide your own, unless you want to throw your exception instead, which would make using Break unnecessary.
You are left with a couple of options then, since I believe usage of Break is unnecessary in your case.
1) Simply throw an exception on failure
def myFunc(x: Int): String = {
if (x > 10) {
"I am fine"
} else {
throw new RuntimeException("Break happened")
}
}
def usemyFunc(): Unit = {
try {
println("myFunc(11) is " + myFunc(11))
println("myFunc(5) is " + myFunc(5))
} catch {
case e: Throwable => println("myFunc failed with " + e)
}
}
2) Use the Try class (available from Scala 2.10) to return either a value or an exception. This differs from the previous suggestion because it forces the caller to inspect the result and check whether a value is available or not, but makes using the result a bit more cumbersome
import scala.util.Try
def myFunc(x: Int): Try[String] = {
Try {
if (x > 10) {
"I am fine"
} else {
throw new RuntimeException("Break happened")
}
}
}
def useMyFunc(): Unit = {
myFunc match {
case Try.Success(s) => println("myFunc succeded with " + s)
case Try.Failure(e) => println("myFunc failed with " + e)
}
}
3) If the thrown exception isn't relevant, you can use the Option class instead.
You can see how the multiple ways of working with Options relate to each other in
this great cheat sheet.
def myFunc(x: Int): Option[String] = {
if (x > 10) {
Some("I am fine") /* Some(value) creates an Option containing value */
} else {
None /* None represents an Option that has no value */
}
}
/* There are multiple ways to work with Option instances.
One of them is using pattern matching. */
def useMyFunc(): Unit = {
myFunc(10) match {
case Some(s) => println("myFunc succeded with " + s)
case None => println("myFunc failed")
}
}
/* Another one is using the map, flatMap, getOrElse, etc methods.
They usually take a function as a parameter, which is only executed
if some condition is met.
map only runs the received function if the Option contains a value,
and passes said value as a parameter to it. It then takes the result
of the function application, and creates a new Option containing it.
getOrElse checks if the Option contains a value. If it does, it is returned
directly. If it does not, then the result of the function passed to it
is returned instead.
Chaining map and getOrElse is a common idiom meaning roughly 'transform the value
contained in this Option using this code, but if there is no value, return whatever
this other piece of code returns instead'.
*/
def useMyFunc2(): Unit = {
val toPrint = myFunc(10).map{ s =>
"myFunc(10) succeded with " + s
}.getOrElse{
"myFunc(10) failed"
}
/* toPrint now contains a message to be printed, depending on whether myFunc
returned a value or not. The Scala compiler is smart enough to infer that
both code paths return String, and make toPrint a String as well. */
println(toPrint)
}
This is a slightly odd way of doing things (throwing an exception), an alternative way of doing this might be to define a "partial function" (a function which is only defined only a specific subset of it's domain a bit like this:
scala> val partial = new PartialFunction[Int, String] {
| def apply(i : Int) = "some string"
| def isDefinedAt(i : Int) = i < 10
}
partial: PartialFunction[Int, String] = <function1>
Once you've defined the function, you can then "lift" it into an Option of type Int, by doing the following:
scala> val partialLifted = partial.lift
partialOpt: Int => Option[String] = <function1>
Then, if you call the function with a value outside your range, you'll get a "None" as a return value, otherwise you'll get your string return value. This makes it much easier to apply flatMaps/ getOrElse logic to the function without having to throw exceptions all over the place...
scala> partialLifted(45)
res7: Option[String] = None
scala> partialLifted(10)
res8: Option[String] = Some(return string)
IMO, this is a slightly more functional way of doing things...hope it helps
In my DSL I want to be able to do like this:
val a = 5
Parse("TYPE") {
a match {
case 3 => info("almost")
case s: String => error("wrong type")
case 5 => info("you won!")
case _ => error("omg")
}
}
with output
[INFO] TYPE: you won!
where Parse is a function object, which has the apply(String), info(String) and error(String) methods:
object Parse {
def apply(name: String)(parseF: => Unit) { parseF }
def info(text: String) { println("[INFO] " + name + ": " + text) }
def error(text: String) { println("[ERROR] " + name + ": " + text) }
}
The trick is that the output of the info and error methods should be somehow native to the Parse object and construct the message by the example as shown above. Therefore, they
have to be accessible like in the example, without any imports.
have to have the access to the first argument passed to Parse() ("TYPE" in the example).
must not create any instances or extra objects during their working.
This is an ideal description. I think that it will require some more boilerplate. Please suggest, how can I acheive that?
EDIT: my initial guess to declare the info and error methods inside the apply method does not make them visible in the parseF method being passed. Well, unsurprisingly..
Maybe something like this:
object Parse {
val currentName = new util.DynamicVariable("<none>")
def apply(name: String)(parseF: => Unit) = currentName.withValue(name)(parseF)
def info(text: String) = println("[INFO] %s: %s" format (currentName.value, text)
}
// usage
import Parse._ // there's no other way to get ability to call 'info' without 'Parse'.
Parse("TYPE") {
// some code
info("some info") // prints: [INFO] TYPE: some info
}
info("some other info") // prints: [INFO] <none>: some other info
If needed, it's easy to make info throw exception if it is called outside Parse {} block.
There is no solution that satisfies 1-3. You can have 1 and 2 or 2 and 3 with slightly different syntax.
1 and 2)
class Parse(val s:String) {
def info....
}
new Parse("TYPE") {
}
2 and 3)
object Parse {
def apply(s:String)(f:String=>Unit) = ...
}
Parse("TYPE")(s => {
})