Fork me on GitHub

What's the canonical way to do server-side form submission rejection on failure of biff/submit-tx? The authentication plugin has a neat ?error={error} system that helps with displaying feedback to the user about why the submission failed, and I'd like to bring it to a variety of my application's forms. While there are good examples of how to do this based on an HTTP request (via Postmark's success param in the JSON response), I can't seem to find a way to do it on, say, the biff/submit-tx failing because a uniqueness constraint wasn't satisfied.


I don't know the canonical way, but what I use is ring flash responses

Jacob O'Bryant17:03:04

hm, so is the main question how to figure out why submit-tx failed, so you know what error message to show? When possible I'd try to validate the input before passing it to submit-tx. You can always reuse the malli schema you've already defined if it helps. Then if you submit the tx and it still fails, I'm pretty sure you can safely assume it's because of the :biff/ensure-unique transaction function failing. You can wrap submit-tx in a try-catch block (or biff/catchall) and if it throws, show a message about the uniqueness thing (e.g. "username already taken").


At the low level, that’s my question (though I wanted to remain open in the case that I was way off-base). The try/catch + malli solution works perfectly for my use case, though. Will look into Ring Flash as well, since I’d never heard of it until now 👍

👌 1

I'm prepping my password-and-invite supporting plugin for release. What's the best-practice as far as depending on something that a library references, but which an application that depends on the library is essentially guaranteed to also depend on (ie, should my plugin depend on biff)?

Jacob O'Bryant17:03:52

hmmm in general I'd say you definitely want to add your dependency explicitly. The only wrinkle here is that biff is a heavy dependency with loads of stuff in it. I'm trying to think if that might be a problem later. Like you say, anyone using the plugin is practically guaranteed to already be depending on biff... For now I'd say go ahead and add biff to your plugin's deps.edn. and maybe at some point I'll have more thoughts about this...

👍 1
Jacob O'Bryant17:03:07

Pre-2022, Biff was split up into a bunch of individual libs, so you could depend on just the ones you needed if you didn't want all of them. However I decided that wasn't worth the trouble and put everything in one lib. I have been thinking that if someone did ever want to not pull in one of Biff's dependencies, I could provide mock versions for all of Biff's largest dependencies. e.g. say you start using a different web server and don't want to bring in the jetty dependency anymore--you add com.biffweb/jetty-mock to deps.edn, and add :exclusions [info.sunng/ring-jetty9-adapter] to your biff dependency. the jetty mock lib includes dummy functions (that throw an UnsupportedOperationException) for all of the jetty functions that biff calls. Since it's part of the Biff project, it'd be guaranteed to stay up to date. (i.e. you could provide your own jetty mock lib, but it might break if I start calling more jetty functions in a new version of biff). So theoretically, someone could follow the same approach for plugins--add :exclusions both to biff and to any plugins.

Jacob O'Bryant17:03:42

That being said, it might not hurt to break out some of biff into separate libs. I've been thinking about a biff-xtdb lib for a while, which would give you access to submit-tx. And then possibly a biff-util lib with all the random functions in biff that don't have heavy dependencies. I'm guessing that would have most of the stuff that plugins need, so you'd be able to depend on just those.

Jacob O'Bryant17:03:19

One last semi-related note: assuming you've based your plugin on the default plugin, be sure to replace any required com.biffweb.impl.* namespaces with com.biffweb , since the latter is the public interface with backwards-compatibility guarantees


ah; hrmm - I just used the .impl namespaces. Is everything used definitely exposed through the top level one?


no need for you to check; I'll find out shortly


(right after I figure out why something I tested is broken now that I'm using the plugin as a library) 😛

Jacob O'Bryant18:03:05

🙂 I should've given you a heads up about that earlier! > Is everything used definitely exposed through the top level one? Not definitely, but I'm pretty sure everything I used in the auth plugin is there. And if it's not, you can copy + paste the functions from the impl namespace. I would've just required com.biffweb from there, except it would be a circular dependency. Might not be a bad idea for me to expose plugins in a separate com.biffweb.plugins namespace and then have them use the regular com.biffweb interface as any 3rd party plugins would.

👍 1

everything worked fine with just the namespaces replaced 🙂

🎅 1