There are many similar dao methods in anorm, is it right? - dao

I'm using Play2 with anorm. I think the spirit of anorm is write plain sqls, no magic behind.
But I quickly found I have write a lot of similar dao methods. For example:
case class User(id:Pk[String], username:String, email:String, realname:String, city:String, website:String)
object User {
val simple = get[Pk[String]]("id") ~ get[String]("username") ~ ... get[String]("website") map {
case id ~ username ~ ... ~ website = User(id, username, ..., website)
}
def findByUsername(username:String) = DB.withConnection { implicit connection =>
SQL("select * from users where username={username}").on('username->username).as(simple.singleOpt)
}
def findByEmail(email:String) = DB.withConnection { implicit connection =>
SQL("select * from users where email={email}").on('email->email).as(simple.singleOpt)
}
def findById(id:String) = DB.withConnection { implicit connection =>
SQL("select * from users where id={id}").on('id->id).as(simple.singleOpt)
}
def findByRealname(keyword:String) = DB.withConnection { implicit connection =>
SQL("select * from users where realname like {keyword}").on('keyword->"%"+keyword+"%").as(simple *)
}
// more similar methods
}
There methods are almost the same, exception the where clause has small difference.
So I created a findWhere() method as:
def findWhere(conditon, values:Any*) = ...
That I can call it in actions:
User.findWhere("id=?", id)
User.findWhere("username=?", username)
It works, but I don't think it's recommended by anorm.
What's the best way to solve this problem?

Why do you believe it is not recommended or ok?
Anorm only cares of receiving a SQL query and parsing the result into a case class. If due to your constraints/design you generate that SQL request dinamically, that makes no difference.
The only issue I see is witht he '?' char, which is nto the way Anorm works. I believe it would me more like:
User.findWhere("username", username)
def findWhere(field: String, value: String) = {
SQL("select * from users where "+ field +"={"+ field +"}").on(Symbol(field)->value).as(simple.singleOpt)
}
This is a simple example, extend as required.

Related

Spring cache for specific values #Cacheable annotation

I want to cache a result of a method only when the attribute of the result contains specific values. For example
Class APIOutput(code: Int, message: String)
sealed class Response<out T : Any> : Serializable {
data class Success<out T : Any>(val data: T) : Response<T>()
data class Error(val errorText: String, val errorCode: Int) : Response<Nothing>()
}
#Cacheable(
key = "api-key",
unless = "do something here"
)
fun doApicall(uniqueId: Long): Response<APIOutput> {
//make API call
val output = callAPI(uniqueId)
return Response.Success(output)
}
In the above method, I want to cache the response only when Response.Success.data.code == (long list of codes).
Please note, in the previous line data is nothing but APIOutput object. How could I achieve it using unless or any other approach. I was thinking of writing a function that takes a doApicall method result as input and would return true or false and call that method it as unless="call a method". But I'm not sure how to do it. Any help is highly appreciated.
You can specify an expression to be evaluated in unless using SpEL. The returned value is available as result so you can do something like -
#Cacheable(
key = "api-key",
unless = "#result!=null or #result.success.data.code!=200"
)
fun doApicall(uniqueId: Long): Response<APIOutput> {
//make API call
val output = callAPI(uniqueId)
return Response.Success(output)
}
You can even use Regex in SpEL and can create custom Expression parsers if the existing functionality is not enough for your usecase.
Thanks Yatharth and John! Below is the condition that worked for me. resultcodes in the below expression is a list
#Cacheable(
key = "api-key",
unless = "!(#result instanceof T(com.abc.Response\$Success))
or (#result instanceof T(com.abc.Response\$Success)
and !(T(com.abc.APIStatus).resultCodes.contains(#result.data.code)))"
)
fun doApicall(uniqueId: Long): Response<APIOutput> {
//make API call
val output = callAPI(uniqueId)
return Response.Success(output)
}

Creating dynamic POST /users calls with Gatling in Scala

I am using Gatling to generate a large number of users to test performance issues on my product. I need to be able to dynamically create users with unique fields (like 'email'). So, I'm generating a random number and using it, but it isn't being re-instantiated each time, so the email is only unique on the first pass.
object Users {
def r = new scala.util.Random;
def randNumb() = r.nextInt(Integer.MAX_VALUE)
val numb = randNumb()
val createUser = {
exec(http("Create User")
.post("/users")
.body(StringBody(raw"""{"email": "qa_user_$numb#company.com" }""")))
}
}
val runCreateUsers = scenario("Create Users").exec(Users.createUser)
setUp(
runCreateUsers.inject(constantUsersPerSec(10) during(1 seconds))
).protocols(httpConf)
Where should I be defining my random numbers? How can I pass it into createUser?
Use a feeder:
object Users {
val createUser = exec(http("Create User")
.post("/users")
.body(StringBody("""{"email": "qa_user_${numb}#Marqeta.com" }""")))
}
val numbers = Iterator.continually(Map("numb" -> scala.util.Random.nextInt(Int.MaxValue)))
val runCreateUsers = scenario("Create Users")
.feed(numbers)
.exec(Users.createUser)
...

How to store parameters for action to be used again later

I have a list view that can be sorted, searched and filtered. From that list view the user can edit items in multiple steps. Finally after editing and reviewing the changes the user goes back to the list. Now I want the list to use the same sorting, search term and filters that the user set before and show the correct results.
How can multiple paramters (sorting, search, filter) be stored and reused when showing the list action?
Possible unsatisfactory ways that I thought of:
pass through all the needed parameters. Does work hardly if there are multiple actions involved between the two list action calls
save the parameters in the session object. This seems to require a lot of code to handle multiple parameters (check if parameter was passed to action, store new value, if parameter was not passed, get old parameter from session, handle empty string parameters):
Long longParameter
if(params.containsKey('longParameter')) {
longParameter = params.getLong('longParameter')
session.setAttribute('longParameter', longParameter)
} else {
longParameter = session.getAttribute('longParameter') as Long
params['longParameter'] = longParameter
}
If you want to make it more generic you could use an Interceptor instead.
This could perhaps be generalized like this:
class SessionParamInterceptor {
SessionParamInterceptor() {
matchAll() // You could match only controllers that are relevant.
}
static final List<String> sessionParams = ['myParam','otherParam','coolParam']
boolean before() {
sessionParams.each {
// If the request contains param, then set it in session
if (params.containsKey(it)) {
session[it] = params[it]
} else {
// Else, get the value from session (it will be null, if not present)
params[it] = session[it]
}
}
true
}
}
The static sessionParams holds the parameters you want to store/retrieve from session.
If the params contains an element from the list, it is stored in session under the same name. If not, it is taken from session (given that it exists).
In your controller, you can now just access params.getLong('theParam') like you always would. You could also use Grails parameter conversion:
def myAction(Long theParam) {
}
Lots of LOC saved.
I use the session as well. Here is a sample that you may adapt to your needs:
def list() {
if (request.method == 'GET' && !request.queryString) {
if (session[controllerName]) {
// Recall params from memory
params.putAll(session[controllerName])
}
} else {
// Save params to memory and redirect to get clean URL
session[controllerName] = extractParams(params)
redirect(action: actionName)
return
}
// Do your actions here...
}
def extractParams(params) {
def ret = [:]
params.each { entry ->
if (entry.key.startsWith("filter_") || entry.key == "max" || entry.key == "offset" || entry.key == "sort" || entry.key == "order") {
ret[entry.key] = entry.value
}
}
return ret
}
Using session is your best bet. Just save the preference when preferred. I mean, when user sorts, or filter, just save that information in the session, for that particular <controller>.<action>, before returning the page. Next time, check the session, if it has anything related to that <controller>.<action>, apply those; otherwise render the default page.
You might like to use some Interceptor for this, as suggested by sbglasius, here.
I hope you're getting my point.

Scala unique validation, PlayFramework, Scalaz

I've found some limitations in Play Faramework default Validation.
My biggest limitation is uniqueness validation.
Let say I'm Validating user registration form and i want to check if passed login already exists.
To do so, i need to ask db to count users by name
UsersService.countByName(s: String): Future[Long]
Is there a posiblity to solve this problem using scalaz Validation and |#|?
case class RegistrationForm(login: String)
object RegistrationForm {
def nonEmptyLogin(login: String): ValidationNel[String, String] = {
if(login.isEmpty)
"validation.error.blank.login".failureNel
else
login.successNel
}
def isLoginUnique(login: String): Future[ValidationNel[String, String]] = {
???
}
def validate(registrationForm: RegistrationForm): Future[ValidationNel[String, RegistrationForm]] = {
nonEmptyLogin(registrationForm.login) |#|
isLoginUnique(registrationForm.login) {
(_) => registrationForm
}
}
}
How should I implement the isLoginUnique method?
I'm not sure if I wrote validdate method correctly either. I just wanted to show my vision of validation.

Cohesive way to validate a class in Scala using Scalaz 7

My goal is to validate User's fields within the object's applymethod before creating one effective User instance:
case class User(String userName, String password)
object User {
def apply(userValidator: UserValidator): ValidationNel[UserCreationFailure, User] = {
//call UserValidator's validate() method here and initialize effective User instance.
}
}
I chose to use Validation from Scalaz7 to accumulate potential illegal arguments / errors.
One drawback in the following code is that Scalaz7 API force me to make the validator creates itself the instance. However, by following Single-Responsibility principle, it's clearly not its role. Its role would be to just validate fields and to return some errors list.
Let's first present my actual code (for information, Empty**** objects are just some case object extending UserCreationFailure):
class UserValidator(val userName: String, val password: String)
extends CommonValidator[UserCreationFailure] {
def validate(): ValidationNel[UserCreationFailure, User] = {
(checkForUserName ⊛
checkForPassword)((userName, password) => new User(userName, password)
}
private def checkForUserName: ValidationNel[UserCreationFailure, String] = {
checkForNonEmptyString(userName) {
EmptyUserName
}
}
def checkForPassword: ValidationNel[UserCreationFailure, String] = {
checkForNonEmptyString(password) {
EmptyPassword
}
}
}
What I would expect is to merely return this snippet code:
(checkForUserName ⊛ checkForPassword)
and bring the appropriate result into my User class, allowing to create the effective instance by doing:
def apply(userValidator: UserValidator): ValidationNel[UserCreationFailure, User] = {
userValidator(username, password).validate()((userName, password)(new User(userName, password))
}
Indeed, it would be more friendly with SRP.
But (checkForUserName ⊛ checkForPassword) returns a totally private type type:
private[scalaz] trait ApplicativeBuilder[M[_], A, B],
thus I don't have the hand on the type of class returned.
Therefore, I am forced to directly associate User's creation with it.
How could I keep SRP and keep this validation mechanism?
-----UPDATE----
As #Travis Brown mentioned, the intent to use an external class for my UserValidator may seem weird. Actually, I expect the validator to be mockable and thus, I'm forced to use composition over trait/abstract class.
I'm not sure I understand why you need a dedicated UserValidator class in the first place. In a case like this I'd be more likely to bundle all of my generic validation code into a separate trait, and to have my User companion object (or whatever other piece I want to be responsible for creating User instances) extend that trait. Here's a quick sketch:
import scalaz._, Scalaz._
trait Validator[E] {
def checkNonEmpty(error: E)(s: String): ValidationNel[E, String] =
if (s.isEmpty) error.failNel else s.successNel
}
sealed trait UserCreationFailure
case object EmptyPassword extends UserCreationFailure
case object EmptyUsername extends UserCreationFailure
case class User(name: String, pass: String)
object User extends Validator[UserCreationFailure] {
def validated(
name: String,
pass: String
): ValidationNel[UserCreationFailure, User] = (
checkNonEmpty(EmptyUsername)(name) |#| checkNonEmpty(EmptyPassword)(pass)
)(apply)
}
And then:
scala> println(User.validated("", ""))
Failure(NonEmptyList(EmptyUsername, EmptyPassword))
scala> println(User.validated("a", ""))
Failure(NonEmptyList(EmptyPassword))
scala> println(User.validated("", "b"))
Failure(NonEmptyList(EmptyUsername))
scala> println(User.validated("a", "b"))
Success(User(a,b))
If you have a huge amount of User-specific validation logic that you don't want polluting your User object, I suppose you could factor it out into a UserValidator trait that would extend your generic Validator and be extended by User.

Resources