7.1 was designed with a Docker first work flow in mind.
Docker allows increased support for Continuous Deployment and Testing, Multi-Cloud Platforms, Environment Standardization and Version Control. As well as better Isolation and Security (stolen from https://dzone.com/articles/5-key-benefits-docker-ci)
- Continuous Deployment
- Challenge meets Skill Level (Expert)
- Eliminates Distractions
- Reduces Worry of Failure
- Testing
- Clear Goals Established
- Clear and Timely Feedback
- Challenge meets Skill Level (Expert)
- Reduces Worry of Failure
- Multi-Cloud Platform support
- Challenge meets Skill Level (Expert)
- Eliminates Distractions
- Reduces Worry of Failure
- Isolation
- Reduces Worry of Failure
- Security
- Reduces Worry of Failure
Base Lucee Image: https://bitbucket.org/blueriver/lucee/src/5d269b26a6e28bffdb21ac70b35325542009656b/5.2.3.35/?at=master
Official Image: https://hub.docker.com/r/blueriver/muracms/
Official Image: https://hub.docker.com/r/blueriver/mura/
Example Dockerfiles: https://github.com/blueriver/docker-muracms
- Eliminates Distractions
- Reduces Worry of Failure
All settings.ini.cfm variables can be set by environmental variables. This is important with stateless cluster and Docker. You can now more easily run your code in different environments from a single repository branch.
You can see examples of how that works in the docker-compose.yml files. Essentially the setting.in.cfm file may not be used in many cases.
In today's modern world where applications are deployed as clustered, stateless, immutable services it's more important than ever to be able configure Mura to store dynamic assets in a scallable object store. This allow any upload asset to immediately available to all services that may request access. This allows you to scale up or down cluster instances as needed.
- Eliminates Distractions
- Reduces Worry of Failure
MURA_ASSETPATH: "https://s3-us-west-1.amazonaws.com/{your_bucket}/"
MURA_S3ASSETS: "s3://{client_id}:{client_secret}@/{your_bucket}/"
MURA_ASSETDIR: "/s3assets"
MURA_FILEDIR: "/s3assets"
In today's modern world where applications are deployed as clustered, stateless, immutable services it's more important than ever to be able configure Mura to store session, data and output caches to use a external services. This allows you to scale up or down cluster instances as needed.
- Eliminates Distractions
- Reduces Worry of Failure
{mura_root}/config/cfapplication.cfm
<cfscript>
this.cache.connections["sessions"] = {
class: 'org.lucee.extension.io.cache.memcache.MemCacheRaw'
, bundleName: 'memcached.extension'
, bundleVersion: '3.0.2.29'
, storage: true
, custom: {
"socket_timeout":"30",
"initial_connections":"1",
"alive_check":"true",
"buffer_size":"1",
"max_spare_connections":"32",
"storage_format":"Binary",
"socket_connect_to":"3",
"min_spare_connections":"1",
"maint_thread_sleep":"5",
"failback":"true",
"max_idle_time":"600",
"max_busy_time":"30",
"nagle_alg":"true",
"failover":"true",
"servers": "memcached:11211"
}
, default: ''
};
this.sessionCluster = true;
this.sessionStorage = "sessions";
/*
{siteid}-data Cache connection for the default site's data cache
This will be used if you have set advancedCaching=true in /config/settings.ini.cfm
or set Mura_ADVANCEDCACHING="true" environment variable
*/
this.cache.connections["default-data"] = {
class: 'org.lucee.extension.io.cache.memcache.MemCacheRaw'
, bundleName: 'memcached.extension'
, bundleVersion: '3.0.2.29'
, storage: true
, custom: {
"socket_timeout":"30",
"initial_connections":"1",
"alive_check":"true",
"buffer_size":"1",
"max_spare_connections":"32",
"storage_format":"Binary",
"socket_connect_to":"3",
"min_spare_connections":"1",
"maint_thread_sleep":"5",
"failback":"true",
"max_idle_time":"600",
"max_busy_time":"30",
"nagle_alg":"true",
"failover":"true",
"servers": "memcached:11211"
}
, default: ''
};
/*
{siteid}-output Cache connection for the default site's output cache
This will be used if you have set advancedCaching=true in /config/settings.ini.cfm
or set Mura_ADVANCEDCACHING="true" environment variable
*/
this.cache.connections["default-output"] = {
class: 'org.lucee.extension.io.cache.memcache.MemCacheRaw'
, bundleName: 'memcached.extension'
, bundleVersion: '3.0.2.29'
, storage: true
, custom: {
"socket_timeout":"30",
"initial_connections":"1",
"alive_check":"true",
"buffer_size":"1",
"max_spare_connections":"32",
"storage_format":"Binary",
"socket_connect_to":"3",
"min_spare_connections":"1",
"maint_thread_sleep":"5",
"failback":"true",
"max_idle_time":"600",
"max_busy_time":"30",
"nagle_alg":"true",
"failover":"true",
"servers": "memcached:11211"
}
, default: ''
};
</cfscript>
With Mura's robust Docker support and full API it can easily be used and content distribution endpoint or be used as a headless CMS.
- Challenge meets Skill Level (Beginner, Novice, Expert)
- Eliminates Distractions
With Mura Scaffolding custom Mura ORM entities can be managed with simple convention based UI. Great for flushing out content to that can be made available via Mura's JSON API.
- Challenge meets Skill Level (Expert)
- Eliminates Distractions
- Reduces Worry of Failure
With Mura's new Assembler super users can now easily define custom Mura entities withou any need to touch code.
- Challenge meets Skill Level (Beginner, Novice)
- Eliminates Distractions
- Reduces Worry of Failure
Mura 7.1 now automatically generates swagger.json files for Mura ORM entities, enabling use of the world's largest api tooling framework.
- Eliminates Distractions
- Reduces Worry of Failure
- Challenge meets Skill Level (Expert)
http://domain.com/index.cfm/_api/json/v1/{siteid}/swagger
http://domain.com/index.cfm/_api/json/v1/{siteid}/swagger?entities={entityname}
Mura 7.1 introduces the ability to do aggregate queries greatly decreasing instances where developers would need to write api helper methods with custom queries against Mura ORM generated schema.
- Eliminates Distractions
- Reduces Worry of Failure
- Challenge meets Skill Level (Beginner, Novice, Expert)
<script>
//This returns generic beans
Mura.getFeed('car')
.aggregate('count','*') //count
.aggregate('sum','price') //sum_price
.aggregate('min','price') //min_price
.aggregate('max','price') //max_price
.aggregate('avg','price') //avg_price
.getQuery()
.then(function(resp){
console.log(resp.getAll());
});
</script>
<cfscript>
rs=Mura.getFeed('car')
.aggregate('count','*') //count
.aggregate('sum','price') //sum_price
.aggregate('min','price') //min_price
.aggregate('max','price') //max_price
.aggregate('avg','price') //avg_price
.getQuery();
//This returns generic beans
iterator=Mura.getFeed('car')
.aggregate('count','*') //count
.aggregate('sum','price') //sum_price
.aggregate('min','price') //min_price
.aggregate('max','price') //max_price
.aggregate('avg','price') //avg_price
.getIterator();
</cfscript>
When the maturity of Mura's containerization and JSON API Mura's javascript utility (Mura.js) is now managed as a separate project. It can easily be embeded in third part evironments and interact with Mura purely as a service through Mura.js JS classes.
- Eliminates Distractions
- Reduces Worry of Failure
https://github.com/blueriver/MuraJS
https://www.npmjs.com/package/mura.js
const express = require('express')
const app = express()
const Mura=require('../index');
Mura.init({
siteid:'default',
rootpath:'http://localhost:8080'
});
app.get('/', function (req, res) {
Mura.getRequestContext(req, res).renderFilename('about').then(
function(content){
res.send("<br/>rendered content:<pre>" + JSON.stringify(content.getAll()) + "</pre>")
},
function(error){
console.log(error);
}
);
})
There is no theme in Mura 7.1 core. There is a new defaultThemeURL settings.ini.cfm attribute
https://github.com/blueriver/MuraCMS/blob/7.1/core/mura/configBean.cfc#L58
That Mura will pull down from on install if no default site theme is found.
If Mura can't get out of the network on install it use it's backup theme
https://github.com/blueriver/MuraCMS/blob/7.1/core/templates/theme.zip.cfm
Mura 7.1 add support for more granual event management syntax. In addidiotn, developers are no longer required to register eventHandlers across entire site or entities classes. You can now register events for specific entities. This allows for more focused business logic and code clarity.
- Eliminates Distractions
- Reduces Worry of Failure
<cfscript>
function onApplicationLoad(Mura){
Mura.getBean('content')
.loadBy(filename='contact')
.on('renderStart',function(Mura){
//WriteDump('test1');abort;
}
);
Mura.siteConfig()
.on('renderStart',function(Mura){
//WriteDump('test2');abort;
}
);
Mura.globalConfig()
.on('renderStart',function(Mura){
//WriteDump('test3');abort;
}
);
Mura.getBean('content')
.loadBy(title='My Form')
.on('submitSave',function(Mura){
//WriteDump('test1');abort;
}
).on('submitResponseRender',function(Mura){
//WriteDump('test1');abort;
}
);
Mura.getBean('widget')
.loadBy(id='...')
.on('beforeSave',function(Mura){
//WriteDump('test1');abort;
}
).on('save',function(Mura){
//WriteDump('test1');abort;
}).on('afterWidgetSave',function(Mura){
//WriteDump('test1');abort;
}
).addEventHandler({
beforeSave=function(Mura){
},
save=function(Mura){
},
afterSave=function(Mura){
}
});
Mura.siteConfig()
.on('beforeWidgetSave',function(Mura){
//WriteDump('test1');abort;
}
).on('widgetSave',function(Mura){
//WriteDump('test1');abort;
}).on('afterWidgetSave',function(Mura){
//WriteDump('test1');abort;
}
).addEventHandler({
renderStart=function(Mura){
},
widgetSave=function(Mura){
},
afterWidgetSave=function(Mura){
}
});
Mura.globalConfig()
.on('beforeWidgetSave',function(Mura){
//WriteDump('test1');abort;
}
).on('widgetSave',function(Mura){
//WriteDump('test1');abort;
}).on('afterWidgetSave',function(Mura){
//WriteDump('test1');abort;
}
).addEventHandler({
beforeWidgetSave=function(Mura){
},
widgetSave=function(Mura){
},
afterWidgetSave=function(Mura){
}
});
}
</cfscript>
<script>
Mura(".myclass").addEventHandler(
{
click:function(a){
},
touch:function(a){
}
}
);
</script>
These are fired when a structured image (associated image) is re-cropped, flipped or rotated and would primarily be use to tell a CDN to clear the existing version from cache
- onBeforeImageManipulation
- onAfterImageManipulation
https://github.com/blueriver/MuraBootstrap3/blob/7.1/templates/inc/html_head.cfm#L16-L18
- Reduces Worry of Failure
In order to prevent Mura instances from having out of sync code bases we have changed the autoupdater to only do complete updates. In addition you can edit the url where it pull from with the new autoupdaterurl settings.ini.cfm atttribute. This allows organizations to use their own code distribution endpoint.
https://github.com/blueriver/MuraCMS/blob/7.1/core/mura/configBean.cfc#L51
- Eliminates Distractions
- Reduces Worry of Failure
In order to reduce un-expected version conflicts between site and core file versions we have eleminated site files. The default theme gets installed in the root/themes directory and the display objects live here:
https://github.com/blueriver/MuraCMS/tree/7.1/core/modules/v1
If we need to make a major change in modules we can add a v2 directory and a contentRenderer.cfc variables to tell each site which modules version to use.
New buddy.works build process that will allow anyone to release a new build.
We probably don't really mention this one. It's basically all internal and it's us basically doing what we are supposed to do. In addition the Buddy.works pipelines are NOT public.
First Run tests https://app.buddy.works/blueriver/muracms/pipelines/pipeline/50718/executions
Tests live here: https://github.com/blueriver/MuraCMS/tree/7.1/core/tests
Then Deploy https://app.buddy.works/blueriver/muracms/pipelines/pipeline/51126/executions