description | icon |
---|---|
This section covers the basics of the program structures of BoxLang |
folder-tree |
BoxLang can be written in 3 types of files:
- Scripts (*.bxs, or in compat mode *.cfs)
- Templates (*.bxm, or in compat mode *.cfm)
- Classes (*.bx or in compat mode *.cfc)
Each of these files follow the same program structure with different syntaxes. The only one of these that you will write using our templating language is the templates (*.bxm)
.
Scripts and templates in BoxLang do not require a class definition and can be executed via the CLI binary directly: boxlang {script|template|
or ran by the MiniServer/CommandBox/Servlet/Etc.
Script files have a bxs
file extension and will use script notation, but you can also use the templating language by using opening and closing tag island notations: ```
a = [1,2,3,4]
user = { name : "boxlang", id : createUUID(), age : 3 }
today = now()
```
<!--- Now I can do templating --->
<bx:output>
Today is #today#<br>
#a.toString()#<br>
#user.toString()#<br>
</bx:output>
```
// Now I am back in scripts
echo( "scripts again" )
Templates have a bxm
file extension and will use the templating language but can also use scripts via opening and closing <bx:script></bx:script>
tags.
<bx:set a = [1,2,3,4]>
<bx:set user = { name : "boxlang", id : createUUID(), age : 3 }>
<bx:set today = now()>
<bx:output>
Today is #today#<br>
#a.toString()#<br>
#user.toString()#<br>
</bx:output>
Classes have a .bx
extension and can be executed via the CLI if they have a main()
method by convention. Unlike Java or other languages, the main()
method does NOT have to be static, it can be an instance method or a static method, you chose.
class{
function main( args = [] ){
println( "BoxLang Rulez!" )
}
}
Package names are not necessary for these types of files as BoxLang will automatically create them for you. You will refer to these scripts or templates by path location or via mappings.
BoxLang allows you to access any BoxLang class or script/template by location convention first with no need of imports explicitly. The following approaches can be used via path imports:
new class_path()
createObject( "class", path )
include template="path"
Any BIF that requires a path
{% hint style="info" %} The discovery is done by looking at your global, application mappings and then relative pathing. {% endhint %}
script.bxs
+ models
+ User.bx
+ scripts
+ data.bxs
Then we can do so my location reference:
{% code title="script.bxs" %}
// Create a new user
user = new models.User( "luis", "majano" )
println( user.getFullName() )
// Now I need to include another script here
include template="scripts/data/bxs"
{% endcode %}
These work great but the caveat is that when searching for those files and templates, BoxLang will try to discover them:
- Is there a location mapping (globally or in the application)
- does the file exist
- use it
Works great, but yes, some lookup is done, but cached.
Another approach in BoxLang is to use the import
statement or the <bx:import>
template statement if you are in templates. This allows you to fully define the location of a class or template explicitly. This is also used not only for BoxLang classes but for any Java class:
import java.time.Instant
import models.User
import ortus.boxlang.runtime.scopes.Key
today = Instant.now()
println( today )
myUser = new User()
caseInsensitiveKey = new Key( "luis" )
From the example above I made no distinction on what was a Java class or what was a Boxlang class. By convention BoxLang will auto-discover the class for you according to it's package path. However, you can also use object resolver notation to disambiguiate the location and define it explicitly.
{% hint style="info" %}
The implicit resolver is bx
meaning a Boxlang class. You don't need to use it if you don't want to.
{% endhint %}
BoxLang ships with two object resolver prefixes:
java:
- To demarcate a Java class pathbx:
- To demarcate a BoxLang class path
This is useful to disambiguiate paths and make them explicit. You can use it in the import or in the new() or createObject()
syntax.
import java:java.time.Instant
import java:ortus.boxlang.runtime.scopes.Key
import models.User
a = Instant.now()
myUser = new User()
caseInsensitiveKey = new java:Key( "luis" )
In box templates and scripts you can add the import/<bx:import>
statements ANYWHERE in the file. We will collect them internally for you.
import java:java.time.Instant
a = Instant.now()
import models.User
myUser = new User()
import java:ortus.boxlang.runtime.scopes.Key
caseInsensitiveKey = new java:Key( "luis" )
Boxlang, like Java, allows you to import all classes from a package using the *
after the last package path. All classes within that package/folder will be available for shorthand usage and reserved.
// Without star imports
import java.util.ArrayList
import java.util.HashMap
myList = new ArrayList()
myList.add( "apple" )
myList.add( "pear" )
myJavaMap = new HashMap()
myJavaMap.put( "name", "boxlang" )
Now let's use start imports
// Without star imports
import java.util.*
myList = new ArrayList()
myList.add( "apple" )
myList.add( "pear" )
myJavaMap = new HashMap()
myJavaMap.put( "name", "boxlang" )
This can be for both Java and BoxLang class paths.
BoxLang allows you to alias your imports in order to break ambiguity and to be able to import classes with the same name but with different aliases.
import java.time.Instant as jInstant
import models.User as BXUser
import models.util.Key
import ortus.boxlang.runtime.scopes.Key as jKey
result = jInstant.now()
user = new BXUser()
caseInsensitiveKey = new Key( "luis" )
javaKey = new jKey( "java" )
Here is another example:
import java.util.Date
import java.sql.Date as SQLDate
d1 = new Date( 1000 )
d2 = new SQLDate( 1000 )
assert d1 instanceof "java.util.Date"
assert d2 instanceof "java.sql.Date"