Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The mapping DSL is the way to configure object mappings in WireBox that will represent objects, factories or providers. All mappings DSL methods return back an instance of the binder so you can concatenate methods to create readable execution chains.
The chains are divided into three types:
Initiators - Start the mapping DSL process
Modifiers - Can modify a mapping with metadata and behavior
Destinations - Tells the binder to what object or behavior we should map to.
If a mapping does not have a destination, then the information stored in the chain can bleed into other mappings.
Ok, now that we know how to configure WireBox, let's get into the fun stuff of object mapping. How do we do this? By using our DSL mapping initiators that tell WireBox how to start the object registration process. You will then concatenate the initiators with some DSL destinations methods, DI data, etc to tell WireBox all the information it might need to construct, wire and persist the object. Here are the DSL initiators:
Caution From the methods we have seen above only the map()
and with()
methods require a DSL destination.
Method Signature
Description
map(alias)
The method that starts the mapping process. You pass in a mapping name or a list of names to start registering
mapPath(path)
Map a CFC instantiation path. This method internally delivers a two-fold punch of doing map('CFCFileName').to(path)
. This is a quick way to map a CFC instantiation path that uses the name of the CFC as the mapping name
mapDirectory(packagePath,[include],[exclude], [influence], [filter], [ namespace],[prepend], [process=false])
A cool method that tells WireBox to automatically register ALL the CFCs found recursively in that instantiation package path. All CFCs will be registered using their CFC names as the mapping names and WireBox will inspect all the CFCs immediately for DI metadata. The include and exclude arguments can be used for inclusions/exclusions lists via regex. The influence argument can be a UDF or closure that will affect the iterating registrations of objects. The filter argument can be a UDF or closure that will filter out or in the CFCs found, an include/exclude on steroids
unMap(alias)
Unmap/delete a mapping in the binder
with(alias)
This method is a utility method that retrieves the alias mapping so you can start concatenating methods for that specific mapping. Basically putting it into a workable context
The mapDirectory()
allows you to leverage closures or lambdas to influence and filter mappings. The arguments are filter
to add a filter that MUST return boolean in order to process the mapping and influence
that can influence the created mapping with any custom bindings.
The mapping destinations tell WireBox what type of object you are mapping to. You will usually use these methods by concatenating map()
or with()
initiator calls:
Here are some examples:
Caution Please note that WireBox can create different types of objects for DI. However, only CFCs will be inspected for autowiring automatically unless you specifically tell WireBox that a certain mapping should not be autowired. In this case you will use the dependencies DSL to define all DI relationships.
The next step in our mapping DSL excursion is to learn about how WireBox will persist these object mappings into WireBox scopes. By default (as we have seen), all object mappings are transient objects and they belong to a scope type called NOSCOPE.
However, we need to specifically tell WireBox into what scope the declared mapped objects should be placed on in order for us to leverage caching, the singleton pattern, etc. This is accomplished by leveraging our persistence component annotations or the following methods if you prefer a non-annotation approach:
Note Please note that all WireBox configuration binders have two public properties:
These classes have on themselves several public properties that are a cool shorthand way to link to construction types or persistence scopes
So just remember that these persistence DSL methods are not mandatory. If you are an annotations kinda developer, then you can easily add these persistence annotations to your classes.
Caution Please note that by leveraging scopes that can expire such as cachebox,request,session,applications,etc you must take into account the way they are injected into other objects. They can experience a DI side effect called scope widening injection that can link an object reference that expires into another object reference that does not expire (like singleton). This causes nasty side effects and issues, so please refer to the WireBox Providers section to find out how you can avoid this nasty pitfall by using WireBox providers.
You can store a-la-carte attributes in a specific mapping so it can be retrieved at a later time by either an AOP aspect or Events. This is a great way to store custom metadata about an object so it can be read later for some meaningful purpose. Let's say you want to tag a mapping with a custom type that is not so easily determined from the object instance itself. You don't want to do all kinds of introspection in order to know what object you received in an aspect or an event.
This mapping declares that an object has some extra attributes that will be stored in the mapping, such as the location and if it belongs to a module. This is then incredibly useful when you have an attached listener to WireBox:
As you can see from this sample, the extra attributes are incredibly essential, as the listener just sends the target object. It would take lots of introspection and metadata inspections in order to determine certain metadata about an object. However, with the extra attributes, it is just a snap!
The dependencies DSL methods are mostly used to define dependencies and also to activate advanced features on target objects, such as runtime mixins, virtual inheritance, etc.
Note Please note that you can concatenate more than one of these methods calls to dictate multiple constructor arguments, setter methods, cf properties, and more.
Method Signature
Description
to(path)
Maps a name to a CFC instantiation path
toDSL(dsl)
Maps a name to DSL builder string. Construction is done by using this DSL string (Look at Injection DSL)
toFactoryMethod(factory,method)
Maps a name to another mapping (factory) and its method call. If you would like to pass in parameters to this factory method call you will use the methodArg()
DSL method concatenated to this method call
toJava(path)
Maps a name to a Java class that can be instantiated via createObject("java")
toProvider(provider)
Maps a name to another mapping (provider) that must implement the WireBox Provider interface (coldbox.system.ioc.IProvider
)
toRSS(path)
Maps a name to an atom or RSS URL. WireBox will then use the cffeed
tag to construct this RSS feed. It builds out into a structure with two keys: metadata : The metadata of the feed items : The items in the feed
toValue(value)
Maps a name to a constant value, which can be ANYTHING.
toWebservice(path)
Maps a name to a webservice WSDL URL. WireBox will create the webservice via createObject("webservice")
for you.
Method Signature | Description |
| Tells WireBox which constructor to call on the mapped object. By default if an object has an |
| Tells WireBox that this mapped object will skip the constructor call for it. By default WireBox always calls object constructors |
| Tells WireBox that the mapped object should be constructed and then wired with a strict concurrency lock for property injections, setter injections and onDIComplete(). Please be aware that if you use this mode of construction, circular dependencies are not allowed. The default is that property and setter injections and onDIComplete() are outside of the construction locks |
| Tells WireBox to construct objects by locking only the constructor and constructor argument dependencies to allow for circular dependencies. This is the default construction mode of all persisted objects: singleton, session, server, application and cachebox scope |
| Tells WireBox that this mapped object has its dependencies described programmatically instead of using metadata inspection to discover them |
| Tells WireBox that this mapped object has a parent mapping with definitions it should use to base it from. This feature provides a great way to reuse object mapping definitions |
| Used to define a constructor argument for the mapped object.
|
| You can pass as many arguments (named or positional) to this method to simulate the |
| Used to define a factory method argument for the mapped object when using a factory method construction.
|
| Used to define a property mixin that will occur at runtime.
|
| Used to define all the setter dependencies for a mapped object that follows the JavaBean spec: |
| A UDF template, a list of templates or an array of templates that WireBox should use to mix-in into the target object. It will take all the methods defined in those UDF templates and mixed them into the target object at runtime. |
| Will inject a new method or override a method on the target object with a new method that provides objects of the mapping you specify. |
| Create a runtime virtual inheritance from a target object into a target mapping. This approach blends the CFCs together at runtime via mixins and WireBox Funkyness! |
| Allows the ability to store extra metadata about a mapping into WireBox that can later be retrieved via AOP invocations or WireBox events. |
| Influence the creation process of a single object. The instance is already built and then passed into the closure for additional influence. You can optionally return the object and it will override it. |
Since version 5.5.0 all mappings in WireBox will only be processed when they are requested for the very first time. This is to enhance performance and increase startup times. Processing means that the object's and its inheritance trail are inspected for metadata, which can be a very time consuming process.
However, you can explicitly process a mapping right after mapping it via the binder's process()
method.
That's it! If you call the process()
method right after a mapping, it will be automatically processed. This means all annotations will be inspected.
If you are mapping using mapDirectory() then you can pass the process
argument to true and all mappings in that directory scan will be processed automatically.
You can use our mapping DSL to register influence closures or lambdas on a per mapping basis. This will allow a developer to influence the requested instance of any object/data element and decorate objects or even return different objects.
This is similar to object providers but instead of overriding the ENTIRE creation process of the object like a provider does, the user might want to simply influence the creation of a normal mapping with some additional flair. This is accomplished via the withInfluence
mapping DSL function. It receives a closure as an argument and the closure has the following signature:
Here is an example of adding some nice pizzazz to an object:
In this instance, the instance is already built and then passed into the closure for additional influence. Please note, that the object is returned from the closure. You can make this optional, but if something IS returned, it will override the instance which will allow a developer to replace or decorate the instance as they see fit.
Method Signature | Description |
asSingleton() | Maps an object to the WireBox internal Singleton scope |
into(scope) | Maps an object to a valid WireBox internal scope or any custom registered scopes by using the registered scope name. Valid internal WireBox scopes are: NOSCOPE PROTOTYPE SINGLETON SESSION APPLICATION REQUEST SERVER CACHEBOX |
inCacheBox([key='mappingName'],[timeout],[lastAccessTimeout],[provider='default']) |
asEagerInit() | Maps an object to be created immediately once the Injector is created. By default all object mappings are lazy loaded in construction. |
Maps an object to the integrated instance