I apologize at the outset as this is more of a design question rather than a specific problem so it may not have a simple answer .. Anyway I am developing quite a complex piece of code to process transactions in a warehouse system. The transactions themselves are user defined with switches which determine fields to enter on a screen .. I use a command object to process / validate the form. Many of the validation steps are straightforward but some are a little tricky and have cross dependencies between the screen fields .. So for instance I may prompt for the user to enter a serial reference but if that doesn't uniquely identify a carton I need to ask for a part to go with it .. I then hit the database to validate these combinations .. The screen may also have a document reference for the user to enter .. This in turn may be cross referenced with the part / serial on the screen (by hitting the database) to ensure that the part/serial is for the document .. This continues, depending on what's been defined on the transaction, with more cross references and validations. What I end up with is a lot of 'if this entered and this entered .. validate .. else .. validate' type stuff in the command object and it looks really ugly .. So my questions are : Should I be putting ALL my validation in the command Object (all the database checking etc) or is there somewhere better to put it and is there anything I can do better than all my complicated if/else combos given that this is a command object ? I had thought of creating additional classes which the current command object could kinda spawn , making those validatable and spreading the logic out amongst those .. If anyone would like to chip in i'd appreciate the discussion ..
After Joshua's comments i've started refactoring the code into a service .. It's not complete but it's taking shape ..
#Transactional
class TransactionValidationService {
static enum state {
RECEIPT,
RECEIPT_SERIAL,
RECEIPT_DOCUMENT,
RECEIPT_PART,
RECEIPT_SERIAL_PART,
RECEIPT_SERIAL_DOCUMENT,
RECEIPT_PART_DOCUMENT,
ISSUE,
TRANSFER
}
def validateTransaction(TransactionDetailCommand transaction) {
// Set initial state ..
def currentState
switch (transaction.transactionType.processType) {
case ProcessType.ISSUE:
currentState = state.ISSUE
break
case ProcessType.RECEIPT:
currentState = state.RECEIPT
break
case ProcessType.TRANSFER:
currentState = state.TRANSFER
}
switch (currentState) {
case state.RECEIPT:
if (transaction.serialReference) {
// validateSerialReference
currentState = state.RECEIPT_SERIAL
} else if (transaction.documentHeader) {
// validateReceiptDocument
currentState = state.RECEIPT_DOCUMENT
}
break
case state.RECEIPT_SERIAL:
if (transaction.part) {
// validatePartSerial
currentState = state.RECEIPT_SERIAL_PART
}
if (transaction.documentHeader) {
// validateDocumentPart
currentState = state.RECEIPT_SERIAL_DOCUMENT
}
break
case state.ISSUE:
break
case state.TRANSFER:
break
}
}
}
First off, using command objects to gather this information is the correct choice.
However, implementing complex validation logic within the constraints as custom validators can be a bit overwhelming. You may want to consider injecting a service into your command object then delegating the validation to the service from within the custom validator.
For example
#Validateable
#ToString(includeNames=true)
class MyExampleCommand {
def myValidationService = Holders.grailsApplication.mainContext.myValidationService
String someThing
Long someValue
..
static constraints = {
someThing(
nullable: false,
blank: false,
size:1..20,
validator: { val, obj ->
obj.myValidationService.validateSomeThing(obj)
}
)
...
}
...
}
Related
I'm trying to implement a "search as you type" pattern in Java.
The goal of the design is that no change gets lost but at the same time, the (time consuming) search operation should be able to abort early and try with the updated pattern.
Here is what I've come up so far (Java 8 pseudocode):
AtomicReference<String> patternRef
AtomicLong modificationCount
ReentrantLock busy;
Consumer<List<ResultType>> resultConsumer;
// This is called in a background thread every time the user presses a key
void search(String pattern) {
// Update the pattern
synchronized {
patternRef.set(pattern)
modificationCount.inc()
}
try {
if (!busy.tryLock()) {
// Another search is already running, let it handle the change
return;
}
// Get local copy of the pattern and modCount
synchronized {
String patternCopy = patternRef.get();
long modCount = modificationCount.get()
}
while (true) {
// Try the search. It will return false when modificationCount changes before the search is finished
boolean success = doSearch(patternCopy, modCount)
if (success) {
// Search completed before modCount was changed again
break
}
// Try again with new pattern+modCount
synchronized {
patternCopy = patternRef.get();
modCount = modificationCount.get()
}
}
} finally {
busy.unlock();
}
}
boolean doSearch(String pattern, long modCount)
... search database ...
if (modCount != modificationCount.get()) {
return false;
}
... prepare results ...
if (modCount != modificationCount.get()) {
return false;
}
resultConsumer.accept(result); // Consumer for the UI code to do something
return modCount == modificationCount.get();
}
Did I miss some important point? A race condition or something similar?
Is there something in Java 8 which would make the code above more simple?
The fundamental problem of this code can be summarized as “trying to achieve atomicity by multiple distinct atomic constructs”. The combination of multiple atomic constructs is not atomic and trying to reestablish atomicity leads to very complicated, usually broken, and inefficient code.
In your case, doSearch’s last check modCount == modificationCount.get() happens while still holding the lock. After that, another thread (or multiple other threads) could update the search string and mod count, followed by finding the lock occupied, hence, concluding that another search is running and will take care.
But that thread doesn’t care after that last modCount == modificationCount.get() check. The caller just does if (success) { break; }, followed by the finally { busy.unlock(); } and returns.
So the answer is, yes, you have potential race conditions.
So, instead of settling on two atomic variables, synchronized blocks, and a ReentrantLock, you should use one atomic construct, e.g. a single atomic variable:
final AtomicReference<String> patternRef = new AtomicReference<>();
Consumer<List<ResultType>> resultConsumer;
// This is called in a background thread every time the user presses a key
void search(String pattern) {
if(patternRef.getAndSet(pattern) != null) return;
// Try the search. doSearch will return false when not completed
while(!doSearch(pattern) || !patternRef.compareAndSet(pattern, null))
pattern = patternRef.get();
}
boolean doSearch(String pattern) {
//... search database ...
if(pattern != (Object)patternRef.get()) {
return false;
}
//... prepare results ...
if(pattern != (Object)patternRef.get()) {
return false;
}
resultConsumer.accept(result); // Consumer for the UI code to do something
return true;
}
Here, a value of null indicates that no search is running, so if a background thread sets this to a non-null value and finds the old value to be null (in an atomic operation), it knows it has to perform the actual search. After the search, it tries to set the reference to null again, using compareAndSet with the pattern used for the search. Thus, it can only succeed if it has not changed again. Otherwise, it will fetch the new value and repeat.
These two atomic updates are already sufficient to ensure that there is only a single search operation at a time while not missing an updated search pattern. The ability of doSearch to return early when it detects a change, is just a nice to have and not required by the caller’s loop.
Note that in this example, the check within doSearch has been reduced to a reference comparison (using a cast to Object to prevent compiler warnings), to demonstrate that it can be as cheap as the int comparison of your original approach. As long as no new string has been set, the reference will be the same.
But, in fact, you could also use a string comparison, i.e. if(!pattern.equals(patternRef.get())) { return false; } without a significant performance degradation. String comparison is not (necessarily) expensive in Java. The first thing, the implementation of String’s equals does, is a reference comparison. So if the string has not changed, it will return true immediately here. Otherwise, it will check the lengths then (unlike C strings, the length is known beforehand) and return false immediately on a mismatch. So in the typical scenario of the user typing another character or pressing backspace, the lengths will differ and the comparison bail out immediately.
Following issue: In a client/server environment with Spring-Boot and Kotlin the client wants to create objects of type A and therefore posts the data through a RESTful endpoint to the server.
Entity A is realized as a data class in Kotlin like this:
data class A(val mandatoryProperty: String)
Business-wise that property (which is a primary key, too) must never be null. However, it is not known by the client, as it gets generated quite expensively by a Spring #Service Bean on the server.
Now, at the endpoint Spring tries to deserialize the client's payload into an object of type A, however, the mandatoryProperty is unknown at that point in time, which would result in a mapping exception.
Several ways to circumvent that problem, none of which really amazes me.
Don't expect an object of type A at the endpoint, but get a bunch of parameters describing A that are passed on until the entity has actually been created and mandatoryProperty is present . Quite cumbersome actually, since there are a lot more properties than just that single one.
Quite similar to 1, but create a DTO. One of my favorites, however, since data classes can't be extended it would mean to duplicate the properties of type A into the DTO (except for the mandatory property) and copy them over. Furthemore, when A grows, the DTO has to grow, too.
Make mandatoryProperty nullable and work with !! operator throughout the code. Probably the worst solution as it foils the sense of nullable and non-nullable variables.
The client would set a dummy value for the mandatoryProperty which is replaced as soon as the property has been generated. However, A is validated by the endpoint and therefore the dummy value must obey its #Pattern constraint. So each dummy value would be a valid primary key, which gives me a bad feeling.
Any other ways I might have overseen that are more feasible?
I don't think there is a general-purpose answer to this... So I will just give you my 2 cents regarding your variants...
Your first variant has a benefit which no other really has, i.e. that you will not use the given objects for anything else then they were designed to be (i.e. endpoint or backend purposes only), which however probably will lead to cumbersome development.
The second variant is nice, but could lead to some other development errors, e.g. when you thought you used the actual A but you were rather operating on the DTO instead.
Variant 3 and 4 are in that regard similar to 2... You may use it as A even though it has all the properties of a DTO only.
So... if you want to go the safe route, i.e. no one should ever use this object for anything else then its specific purpose you should probably use the first variant. 4 sounds rather like a hack. 2 & 3 are probably ok. 3 because you actually have no mandatoryProperty when you use it as DTO...
Still, as you have your favorite (2) and I have one too, I will concentrate on 2 & 3, starting with 2 using a subclass approach with a sealed class as supertype:
sealed class AbstractA {
// just some properties for demo purposes
lateinit var sharedResettable: String
abstract val sharedReadonly: String
}
data class A(
val mandatoryProperty: Long = 0,
override val sharedReadonly: String
// we deliberately do not override the sharedResettable here... also for demo purposes only
) : AbstractA()
data class ADTO(
// this has no mandatoryProperty
override val sharedReadonly: String
) : AbstractA()
Some demo code, demonstrating the usage:
// just some random setup:
val a = A(123, "from backend").apply { sharedResettable = "i am from backend" }
val dto = ADTO("from dto").apply { sharedResettable = "i am dto" }
listOf(a, dto).forEach { anA ->
// somewhere receiving an A... we do not know what it is exactly... it's just an AbstractA
val param: AbstractA = anA
println("Starting with: $param sharedResettable=${param.sharedResettable}")
// set something on it... we do not mind yet, what it is exactly...
param.sharedResettable = UUID.randomUUID().toString()
// now we want to store it... but wait... did we have an A here? or a newly created DTO?
// lets check: (demo purpose again)
when (param) {
is ADTO -> store(param) // which now returns an A
is A -> update(param) // maybe updated also our A so a current A is returned
}.also { certainlyA ->
println("After saving/updating: $certainlyA sharedResettable=${certainlyA.sharedResettable /* this was deliberately not part of the data class toString() */}")
}
}
// assume the following signature for store & update:
fun <T> update(param : T) : T
fun store(a : AbstractA) : A
Sample output:
Starting with: A(mandatoryProperty=123, sharedReadonly=from backend) sharedResettable=i am from backend
After saving/updating: A(mandatoryProperty=123, sharedReadonly=from backend) sharedResettable=ef7a3dc0-a4ac-47f0-8a73-0ca0ef5069fa
Starting with: ADTO(sharedReadonly=from dto) sharedResettable=i am dto
After saving/updating: A(mandatoryProperty=127, sharedReadonly=from dto) sharedResettable=57b8b3a7-fe03-4b16-9ec7-742f292b5786
I did not yet show you the ugly part, but you already mentioned it yourself... How do you transform your ADTO to A and viceversa? I will leave that up to you. There are several approaches here (manually, using reflection or mapping utilities, etc.).
This variant cleanly seperates all the DTO specific from the non-DTO-specific properties. However it will also lead to redundant code (all the override, etc.). But at least you know on which object type you operate and can setup signatures accordingly.
Something like 3 is probably easier to setup and to maintain (regarding the data class itself ;-)) and if you set the boundaries correctly it may even be clear, when there is a null in there and when not... So showing that example too. Starting with a rather annoying variant first (annoying in the sense that it throws an exception when you try accessing the variable if it wasn't set yet), but at least you spare the !! or null-checks here:
data class B(
val sharedOnly : String,
var sharedResettable : String
) {
// why nullable? Let it hurt ;-)
lateinit var mandatoryProperty: ID // ok... Long is not usable with lateinit... that's why there is this ID instead
}
data class ID(val id : Long)
Demo:
val b = B("backend", "resettable")
// println(newB.mandatoryProperty) // uh oh... this hurts now... UninitializedPropertyAccessException on the way
val newB = store(b)
println(newB.mandatoryProperty) // that's now fine...
But: even though accessing mandatoryProperty will throw an Exception it is not visible in the toString nor does it look nice if you need to check whether it already has been initialized (i.e. by using ::mandatoryProperty::isInitialized).
So I show you another variant (meanwhile my favorite, but... uses null):
data class C(val mandatoryProperty: Long?,
val sharedOnly : String,
var sharedResettable : String) {
// this is our DTO constructor:
constructor(sharedOnly: String, sharedResettable: String) : this(null, sharedOnly, sharedResettable)
fun hasID() = mandatoryProperty != null // or isDTO, etc. what you like/need
}
// note: you could extract the val and the method also in its own interface... then you would use an override on the mandatoryProperty above instead
// here is what such an interface may look like:
interface HasID {
val mandatoryProperty: Long?
fun hasID() = mandatoryProperty != null // or isDTO, etc. what you like/need
}
Usage:
val c = C("dto", "resettable") // C(mandatoryProperty=null, sharedOnly=dto, sharedResettable=resettable)
when {
c.hasID() -> update(c)
else -> store(c)
}.also {newC ->
// from now on you should know that you are actually dealing with an object that has everything in place...
println("$newC") // prints: C(mandatoryProperty=123, sharedOnly=dto, sharedResettable=resettable)
}
The last one has the benefit, that you can use the copy-method again, e.g.:
val myNewObj = c.copy(mandatoryProperty = 123) // well, you probably don't do that yourself...
// but the following might rather be a valid case:
val myNewDTO = c.copy(mandatoryProperty = null)
The last one is my favorite as it needs the fewest code and uses a val instead (so also no accidental override is possible or you operate on a copy instead). You could also just add an accessor for the mandatoryProperty if you do not like using ? or !!, e.g.
fun getMandatoryProperty() = mandatoryProperty ?: throw Exception("You didn't set it!")
Finally if you have some helper methods like hasID(isDTO or whatever) in place it might also be clear from the context what you are exactly doing. The most important is probably to setup a convention that everyone understands, so they know when to apply what or when to expect something specific.
This is the current code:
Class %Utcov.Test Extends %RegisteredObject
{
ClassMethod listClasses(ns As %String, projectName As %String)
{
// Switch namespaces to the new one
new $namespace
set $namespace = ns
// Grab our project, by name; fail otherwise
// TODO: failing is CRUDE at this point...
#dim project as %Studio.Project
#dim status as %Status
// TODO: note sure what the "concurrency" parameter is; leave the default
// which is -1
set project = ##class(%Studio.Project).%OpenId(projectName, /* default */, .status)
if ('status) {
write "Argh; failed to load", !
halt // meh... Ugly, f*ing ugly
}
w project.Items
}
ClassMethod main()
{
do ..listClasses("USER", "cache-tort-git")
}
}
First things first: I know that the code sucks... But that's the learning curve, I will eventually do better... The problem I want to solve here is this line:
w project.Items
At the console, it currently prints:
2#%Library.RelationshiptObject
but what I'd like to do is of course to cycle through these objects, which, according to the documentation, are "instances" of %Studio.ProjectItem.
How do I cycle through these? WRITE doesn't cut it, and in fact I surmised from the start that it would not... I just cannot figure out how this is done in ObjectScript :/
When your writed object with w project.Items, you got such string 2#%Library.RelationshiptObject, this string may help in understanding what the object we got, and in this case it is an object of class %Library.RelationshiptObject, when you open this class in documentation, you may find some methods which could help you.
Here you can find some examples, how to work with relationships, in objects way and with sql.
Set tKey = ""
For {
;tItem will be the first item in your list which will be ordered by OREF
Set tItem = project.Items.GetNext(.tKey)
Quit:(tKey = "")
;Do whatever you want with tItem
}
I've been trying to figure out how to do this without manually defining a validation but without any success so far.
I have a StringField
class Foo private() extends MongoRecord[Foo] with ObjectIdKey[Foo] {
...
object externalId extends StringField(this, 255) {
// none of these seem to have any effect on validation whatsoever:
override def optional_? = false
override def required_? = true
override def defaultValueBox = Empty
}
...
}
Now when I call .validate on a Foo, it returns no errors:
val foo = Foo.createRecord
foo.validate match {
case Nil => foo.save
...
}
...and the document is saved into the (mongo) DB with no externalId.
So the question is: is there any way at all to have Lift automatically validate missing fields without me having to manually add stuff to validations?
EDIT: am I thinking too much in terms of the type of productivity that frameworks like Django and Rails provide out of the box? i.e. things like basic and very frequent validation without having to write anything but a few declarative attributes/flags. If yes, why has Lift opted to not provide this sort of stuff out of the box? Why would anybody not want .validate to automatically take into consideration all the def required_? = true/def optional_? = false fields?
As far as I'm aware, there isn't a way for you to validate a field without explicitly defining validations. The reason that optional_? and required_? don't provide validation is that it isn't always clear what logic to use, especially for non String fields. The required_? value itself is used by Crudify to determine whether to mark the field as required in the produced UI, but it's up to you to provide the proper logic to determine that the requirement is satisfied.
Validating the field can be as easy as
override def validations = super.validations :: valMinLen(1, "Required!")
Or see the answer to your other question here for how to create a generic Required trait.
In a Grails service, I create/update domain entities based on an external list. Updates take place in a loop. If the line in the input file is valid, entities are updated. Otherwise, I store the faulty line number and process the next one.
Problem: when I call validate() on an entity, if the result is false, any work done in the service in rolled back, even if does not pertain to the validation, and although no exception is visible. For instance:
assert contact.firstName = 'Bruce'
contact.firstName = 'John'
assert contact.save()
...
company.vat = 'bogus'
if (!company.validate()) {
log.error "bogus"
company.discard()
} else {
assert company.save()
}
log.debug "done"
If company does not validate, my log will show "bogus" and "done". Contact first name will be 'Bruce' in the database, not 'John'.
Alternate version: if I do not call company.validate(), the contact first name is updated.
At this stage, I suspect Grails attaches my company instance upon the validate() call, dooming the transaction when it realizes validations do not pass, and despite the discard() effort.
From the validate() semantic and its javadoc ("Validates an instance"), I didn't expect any side effect, whether the validation fails or not, or whether I even invoke validate() or not.
What do you think? Is this a "normal" bahavior, or a bug? How can I work around this?
I have a simple reproduction case with two entities if needed.
I might be missing something here, but isn't the whole goal of the 'discard' method to not apply the change, and what you're seeing here (not applying the change in case of a validation error) would be logical?
Not able to test it on this setup, but could you set transactional = false in your service, process all the objects (adding the correctly validated objects in one list and saving/logging the failed ones elsewhere), and then finally saving the "good" list of objects using withTransaction? Something like:
static transactional = false
def sessionFactory
List<Company> validCompanies = []
for(Company company: listOfCompaniesToValidate) {
if (!company.validate()) {
log.error "bogus"
} else {
validCompanies.add(company)
}
}
Company.withTransaction {
for (Company validCompany: validCompanies)
validCompany.save()
}
validCompanies.clear()
}
sessionFactory.getCurrentSession().clear();
Just an idea!