The Box
class is a container which is able to declare if it is Full
(containing a single non-null value) or EmptyBox
.
A bridge to make using Lift Box
from Java easier.
A bridge to make using Lift Box
from Java easier.
In particular, provides access to the Box
companion object so that
functions like legacyNullTest
can be used easily
from Java, as well as access to the Empty
singleton so that empty
values can be created easily from Java.
Mix this trait in to get some low-cost implicits for logging boxes easily.
Mix this trait in to get some low-cost implicits for logging boxes
easily. The consumer will need to implement a logBoxError
method to log messages with an optional Throwable
, as well as its related
friends for trace, debug, info, and warn levels. This allows abstracting out
where and what the actual logger is.
With this mixed in, boxes will have logFailure
and
logFailure
methods. The first logs all Failure
s as well
as Empty
. The second logs only Failure
s and
ParamFailure
s, treating Empty
as a valid value. These both log their
respective items at ERROR level. You can also use traceLog*
, debugLog*
,
infoLog*
, and warnLog*
if you want to log at other levels (e.g., you can
use infoLogFailure
to log an Empty
or Failure
at INFO
level).
All of these return the box unchanged, so you can continue to use it
in for
comprehensions, call openOr
on it, etc.
There is an implementation for anyone who wants to use Lift's
Loggable
trait called LoggableBoxLogging
. Another implementaiton
is available for use with a plain SLF4J logger, SLF4JBoxLogging
. You can
also implement a version for any other logging adapter. Lastly, you can
simply import BoxLogging._
to get the methods available at a top level;
however, note that using them this way will lose information about where the
log message came from.
Here is an example of how you might use this in system that executes a third- party service and notifies another system of failures.
val systemResult: Box[ServiceReturn] = system .executeService(true, requester) .map(...) .logFailure("Failed to execute service") match { case Full(content) => content case failure: Failure => otherSystem.notifyFailure(failure) case Empty => otherSystem.notifyFailure(Failure("No idea what happened.")) }
Sometimes it's convenient to access either a Box[T]
or a T
.
Sometimes it's convenient to access either a Box[T]
or a T
. If you
specify BoxOrRaw[T]
, either a T
or a Box[T]
can be passed and the
"right thing" will happen, including null
s being treated as Empty
.
Implementation for the Box
singleton.
A trait that a class can mix into itself to indicate that it can convert
itself into a Box
.
The BoxOrRaw
that represents a boxed value.
A component that takes action around some other functionality.
A component that takes action around some other functionality. It may choose to execute or not execute that functionality, but should not interpret or change the returned value; instead, it should perform orthogonal actions that need to occur around the given functionality. A canonical example is wrapping an SQL transaction around some piece of code.
As an example, this trait defines the principal contract for function objects that wrap the processing of HTTP requests in Lift.
See StringFunc
.
Used as a return type for certain methods that should not be called.
Used as a return type for certain methods that should not be called. One
example is the get
method on a Lift Box
. It exists to prevent client
code from using .get
as an easy way to open a Box
, so it needs a return
type that will match no valid client return types.
An EmptyBox
is a Box
containing no value.
An EmptyBox
is a Box
containing no value. It can sometimes carry
additional failure information, as in Failure
and ParamFailure
.
Encoding for "A is not a subtype of B".
A Failure
is an EmptyBox
with an additional failure message
explaining the reason for its being empty.
A Failure
is an EmptyBox
with an additional failure message
explaining the reason for its being empty. It can also optionally provide an
exception and/or a chain of previous Failure
s that may have caused this
one.
Interface for an actor that can internally forward received messages to other actors.
Full
is a Box
that contains a value.
Bridges from Java functions to Scala functions.
Bridges from Java functions to Scala functions.
The implicits defined here allow Scala code to interact seamlessly between the Java function-like interfaces and the Scala function interfaces for various function arities.
In particular, there is a pair of implicits for each arity of function from 0
to 4. There is one implicit (called lift
) from the Java function type to
the corresponding Scala function type and one (called drop
) from the Scala
function type to the corresponding Java function type.
Generic Actor interface.
Generic Actor interface. Can receive any type of message. Can return (via
!!
and !?
) messages of type R
.
Implements an LRU Hashmap.
Implements an LRU Hashmap. Given a size, this map will evict the least recently used item(s) when new items are added.
Note that LRUMap
is not thread-safe.
If you mix this into your class, you will get a protected logger
instance
lazy val
that will be a Logger
instance.
If you mix this into your class, you will get a protected logger
instance
lazy val
that will be a Logger
instance.
Useful for mixing into objects that are created before Lift has booted (and thus Logging is not yet configured).
If you mix this into your class, you will get a protected logger
instance
val
that will be a Logger
instance.
A version of BoxLogging
with a default implementation of
logBoxError
that logs to the logger provided by Lift's
Loggable
.
Logger
is a thin wrapper on top of an SLF4J Logger.
Logger
is a thin wrapper on top of an SLF4J Logger.
The main purpose is to utilize Scala features for logging.
Note that the dynamic type of "this" is used when this trait is mixed in.
This may not always be what you want. If you need the static type, you have
to declare your own Logger
:
class MyClass { val logger = Logger(classOf[MyClass]) }
A ParamFailure
is a Failure
with an additional type-safe parameter
that can allow an application to store other information related to the
failure.
A ParamFailure
is a Failure
with an additional type-safe parameter
that can allow an application to store other information related to the
failure.
For example:
val loggedInUser = for { username ?~ "Missing username" ~> "error.missingUser" password ?~! "Missing password" ~> "error.missingPassword" user <- User.find("username" -> username) if User.checkPassword(password, user.password) } yield { user } loggedInUser match { case ParamFailure(message, _, _, i18nKey: String) => tellUser(i18n(i18nKey)) case Failure(message, _, _) => tellUser(failureMessage) case Empty => tellUser("Unknown login failure.") case _ => tellUser("You're in!") }
The BoxOrRaw
that represents a raw value.
See StringFunc
.
The simple definition of an actor.
The simple definition of an actor. Something that can be sent a message of
type T
.
An immutable singly linked list that uses the Scala List class as backing
store, but is Java-friendly as a java.util.List
.
An immutable singly linked list that uses the Scala List class as backing
store, but is Java-friendly as a java.util.List
. Note however that since it
is immutable, you have to capture the results of addition/removal operations.
The typical mutating methods like add
, set
, clear
, and remove
are all
unsupported, as are mutating methods on its iterators, since this collection
is immutable.
An immutable vector that uses the Scala Vector
class as backing store, but is Java-friendly as a java.util.List
.
An immutable vector that uses the Scala Vector
class as backing store, but is Java-friendly as a java.util.List
. Note however that
since it is immutable, you have to capture the results of addition/removal
operations.
The typical mutating methods like add
, set
, clear
, and remove
are all
unsupported, as are mutating methods on its iterators, since this collection
is immutable.
"Scala's Collection Library overview" section on Vectors for more information.
An Actor that can receive a message of any type.
Generic Actor interface.
Generic Actor interface. Can receive any type of message.
Can return (via !!
and !?
) messages of any type.
This trait is used to unify ()=>String
and String
into one type.
This trait is used to unify ()=>String
and String
into one type. It is
used in conjunction with the implicit conversions defined in its companion object.
This trait is used to unify String
s and NodeSeq
s
into one type.
This trait is used to unify String
s and NodeSeq
s
into one type. It is used in conjuction with the implicit conversions defined
in its companion object.
An Actor that can receive messsages of type T
and return responses of type
R
.
Represents a Logger
backed by an SLF4J Logger
.
The case class that holds the NodeSeq
constant.
The case class that holds the NodeSeq
constant.
(Since version 3.0) Lift now mostly uses NodeSeq=>NodeSeq
transformations rather
than NodeSeq
constants; consider doing the same.
This trait is used to unify ()=>NodeSeq
and
NodeSeq
into one type.
This trait is used to unify ()=>NodeSeq
and
NodeSeq
into one type. It is used in conjunction
with the implicit conversions defined in its companion
object.
(Since version 3.0) Lift now mostly uses NodeSeq=>NodeSeq
transformations rather
than NodeSeq
constants; consider doing the same.
The case class that holds a NodeSeq
function.
The case class that holds a NodeSeq
function.
(Since version 3.0) Lift now mostly uses NodeSeq=>NodeSeq
transformations rather
than NodeSeq
constants; consider doing the same.
The Box companion object provides methods to create a Box from:
A convenience singleton for BoxLogging
that makes logFailure
and logFailure
available for all code after it's been imported
as import com.elemica.common.BoxLogging._
.
A convenience singleton for BoxLogging
that makes logFailure
and logFailure
available for all code after it's been imported
as import com.elemica.common.BoxLogging._
. Logging done this way
will come from BoxLogging
, not from the class where the box was
logged.
Companion object with implicit conversions to allow BoxOrRaw[T]
to
masquerade as the appropriate types.
Via an HList
containing a collection of Box
, either generates an
HList
of the things (unboxed) or a List[Failure]
.
Singleton object representing a completely empty Box
with no value or
failure information.
The companion object to ExcludeThisType
.
The companion object to ExcludeThisType
. This allows one of specify that a
type is not a subtype of another type.
Based on work by Miles Sabin.
Companion object used to simplify the creation of a simple Failure
with
just a message.
Basic support for heterogeneous lists, aka HLists.
Basic support for heterogeneous lists, aka HLists.
An HList
can be constructed like so:
import net.liftweb.common.HLists._ trait Base case class Type1(value: String) extends Base case class Type2(otherValue: String) extends Base val myHList = Type1("Value") :+: Type2("Other Value") :+: HNil myHList match { case firstThing :+: secondThing :+: HNil => println(firstThing.value) println(secondThing.otherValue) }
Above, we see that the HList
preserved the value of the types of its
members, otherwise we wouldn't have been able to fetch value
and
otherValue
, respectively.
Trying the same thing with a list won't work:
val myList = Type1("Value") :: Type2("Other Value") :: Nil myList match { case firstThing :: secondThing :: Nil => // error: value value is not a member of Product with Serializable with Base println(firstThing.value) }
This is because value
is not defined in Base
. The inferred type of the
List
has to be a common ancestor class or trait of Type1
and Type2
, and
no such type has a value
method.
Configuration helpers for the log4j logging backend.
Configuration helpers for the Logback logging backend.
Provides some helpers to easily create Logger
instances.
Provides some helpers to easily create Logger
instances.
For example:
class MyClass { val logger = Logger(classOf[MyClass]) }
It can also be used to provide global setup for loggers created this way:
Logger.setup = Full(Logback.withFile(new URL("file:///path/to/config.xml"))) class MyClass { val logger = Logger(classOf[MyClass]) logger.debug("Hello") // uses the above configuration }
Last but not least, you can wrap chunks of code with particular Mapped Diagnostic Context values:
Logger.logWith("mykey" -> "value") { logger.debug("stuff") // has mykey set to value in the MDC } logger.debug("more stuff") // mykey is set to its previous value
The Mapped Diagnostics Context can hold values per thread and output them with each logged output.
The Mapped Diagnostics Context can hold values per thread and output them with each logged output.
The logging backend needs to be configured to log these values.
Companion object used to simplify the creation of simple ParamFailure
s, as
well as allow pattern-matching on the ParamFailure
.
Provides implicit conversions to the StringFunc
trait.
Provides implicit conversions to the StringFunc
trait. This allows using a
String
as a natural part of APIs that want to allow the flexibility of a
()=>String
without having to write overloads for all methods that should
accept both.
Lift's Menu API, for example, allows CSS classes to be defined either as
a String
or a ()=>String
. The latter could use the current request and
session state to do more interesting things than a hard-coded String
would,
while the former is simpler to use.
Provides implicit conversions to the StringOrNodeSeq
trait, which can in
turn be implicitly converted to NodeSeq
.
Provides implicit conversions to the StringOrNodeSeq
trait, which can in
turn be implicitly converted to NodeSeq
. This allows
using a String
as a natural part of NodeSeq
APIs without having to
explicitly wrap it in scala.xml.Text
or having to write overloads for all
methods that should accept both.
This is used in certain Lift APIs, for example, to accept either a String
or more complex content. For example, a button
can have either a simple
label or complex HTML content. HTML APIs that can do this can accept a
parameter of type StringOrNodeSeq
to allow the user to pass either in as
their needs dictate.
Provides implicit conversions to the NodeSeqFunc
trait.
Provides implicit conversions to the NodeSeqFunc
trait. This allows using a
NodeSeq
as a natural part of APIs that want to allow
the flexibility of a ()=>NodeSeq
without having to
write overloads for all methods that should accept both.
(Since version 3.0) Lift now mostly uses NodeSeq=>NodeSeq
transformations rather
than NodeSeq
constants; consider doing the same.
The
Box
class is a container which is able to declare if it isFull
(containing a single non-null value) orEmptyBox
. AnEmptyBox
, or empty, can be theEmpty
singleton,Failure
orParamFailure
.Failure
andParamFailure
contain information about why theBox
is empty including exception information, possibly chainedFailure
s and aString
message.This serves a similar purpose to the
Option
class from Scala standard library but adds several features:Failure
object if it isEmpty
(with the?~
orfailMsg
method).Failure
s (with the?~!
orcompoundFailMsg
method).Box
, with a default to return if the box isEmpty
:Box
to a function for side effects:Exceptions and Empty Box Handling
If you grew up on Java, you're used to
Exception
s as part of your program logic. The Scala philosophy and the Lift philosophy is that exceptions are for exceptional conditions such as failure of an external resource (e.g., your database goes offline) rather than simply indicating that a parameter wasn't supplied or couldn't be parsed.Lift's
Box
and Scala'sOption
provide mechanisms for being explicit about a value existing or not existing rather than relying on a reference being not-null. However, extracting a value from aBox
should be done correctly. Available options are:for
comprehension, especially for multiple boxes:map
,flatMap
,filter
, andforeach
(for
comprehensions use these under the covers):Failure
s):==
and===
: