Migrating Genie apps from v4 to v5
Genie v5 is a major update to the Genie framework that introduces many new features and improvements. These include a nimble core architecture with many previously bundled features being now moved to stand-alone packages (cache, deployment, etc), the removal of legacy code and APIs, performance refactoring, restructuring of the core framework and APIs, and many other reliability, usability and performance improvements.
Support for Genie v4
Despite introducing breaking changes, the upgrade from Genie v4 to v5 should be quite straightforward and should not take a long time. All users are recommended to upgrade to Genie v5.
While we will not backport compatible features from Genie 5 to Genie 4, we will continue to support the v4 API for the foreseeable period of time and we will backport compatible security patches.
Genie v4 and Julia v1.8 compatibility issue: modules_warned_for not defined
Due to an issue caused by the removal of some APIs in Julia 1.8, Genie v4 apps can not run on Julia 1.8. This results in a LoadError: UndefVarError: modules_warned_for not defined
exception when loading a Genie v4 app on Julia 1.8 and above.
Addressing the issue: modules_warned_for not defined
The obvious and immediate solution is to simply go ahead and comment out the offending line – the exact line will depend on your specific app, but it's line 4 in bootstrap.jl
and starts with push!(Base.modules_warned_for, Base.PkgId
.
However, this only eliminates the source of the exception. But it's possible that the Genie v4 app will still not run on Julia 1.8 and above as is, due to the fact that the loading of resources (controllers and models) in the app no longer works. So if the app does not work, mainly due to exceptions mentioning that the app does not have some controller or model "in its dependencies", this is the reason. The only way to fix this is to upgrade to Genie v5 and update your app to support Genie v5 by following the following steps.
Upgrade from v4 to v5
However, some of these deep changes come at the cost of breaking compatibility with older apps that were developed using Genie v4. This guide will walk you through the process of migrating a Genie app from v4 to v5. The following changes need to be made to various Genie v4 application files. Each section indicates the file that needs to be modified.
1. config/secrets.jl
In Genie v5, Genie.secret_token!
has been moved to a dedicated module called Secrets
, so the config/secrets.jl
file needs to be updated to include the new module.
Genie.Secrets.secret_token!("<your-secret-token>")
2. config/initializers/ssl.jl
Genie v5 completely removed the legacy config/initializers/ssl.jl
file. This provided a crude way of setting up SSL support for local development that was limited and not reliable. In Genie v5 the recommended approach is to set up SSL at the proxy server level, for example by using Caddy, Nginx, or Apache as a reverse proxy.
So just remove the config/initializers/ssl.jl
file.
julia> rm("config/initializers/ssl.jl")
3. app/helpers/ViewHelper.jl
The output_flash
function defined in the ViewHelper
file uses the flash
function which relied on Genie.Session
in Genie v4. In Genie v5, Genie.Session
has been moved to a dedicated plugin called GenieSession.jl
. In addition, GenieSession.jl
is designed to support multiple backends for session storage (file system, database, etc) so we also need to add a backend, such as GenieSessionFileSession.jl
.
If your app uses the output_flash
function then you need to add GenieSession.jl
as a dependency of your app and update the ViewHelper
file to use the GenieSession.Flash.flash
function.
module ViewHelper
using GenieSession, GenieSessionFileSession, GenieSession.Flash
export output_flash
function output_flash(flashtype::String = "danger") :: String
flash_has_message() ? """<div class="alert alert-$flashtype alert-dismissable">$(flash())</div>""" : ""
end
end
If your app does not use output_flash
then you can just remove the ViewHelper
file.
julia> rm("app/helpers/ViewHelper.jl")
4. All references to app resources (controllers and models)
In Genie v5, the app resources such as controllers and models were accessible directly in routes.jl
and in any other resource. For instance, let's say that we have:
- a controller called
HomeController
- a model called
Home
- our app (aka our project's main module) is called
WelcomeHome
(meaning that we have a filesrc/WelcomeHome.jl
)
In v4 we could access them directly in routes.jl
(or in other controllers and models) as using HomeController, Home
.
However, in Genie v5 all the app's resources are scoped to the app's main module. So we need to update all references to the app resources to use the app's main module, meaning that in v5 we'll need using WelcomeHome.HomeController, WelcomeHome.Home
.
We can also dynamically reference the app's main module by using ..Main.UserApp
(so ..Main.UserApp
is the same as WelcomeHome
in our example).
5. Genie.Cache
In Genie v5, the Genie.Cache
module has been moved to a dedicated plugin called GenieCache.jl
. This means that all references to Genie.Cache
need to be updated to use GenieCache
.
This change was made to provide a leaner Genie core, making caching features opt-in. But also to allow the independent development of the caching features, independent from Genie itself.
6. Genie.Cache.FileCache
Starting with Genie 5, the file-based caching functionality provided by Genie.Cache.FileCache
has been moved to a dedicated plugin called GenieCacheFileCache.jl
. This means that all references to Genie.Cache.FileCache
need to be updated to use GenieCacheFileCache
. The GenieCacheFileCache
plugin is dependent on the GenieCache
package and it extends the functionality of GenieCache
.
In the future, additional cache backends will be released.
7. Genie.Session
As mentioned above, the Genie.Session
module has been moved to a dedicated plugin called GenieSession.jl
. This means that all references to Genie.Session
need to be updated to use GenieSession
.
This change was made to provide a leaner Genie core, making session related features opt-in. But also to allow the independent development of the session features, independent from Genie itself.
8. Genie.Session.FileSession
Starting with Genie 5, the file-based session storage provided by Genie.Session.FileSession
has been moved to a dedicated plugin called GenieSessionFileSession.jl
. This means that all references to Genie.Session.FileSession
need to be updated to use GenieSessionFileSession
. The GenieSessionFileSession
plugin is dependent on the GenieSession
package and it extends the functionality of GenieSession
.
In the future, additional session storage backends will be released.
9. Genie.Deploy
Similar to Genie.Session
and Genie.Cache
, the Genie.Deploy
module has been moved to a dedicated plugin called GenieDeploy.jl
. This means that all references to Genie.Deploy
need to be updated to use GenieDeploy
.
10. Genie.Deploy.Docker
Starting with Genie 5, the Docker
deployment functionality provided by Genie.Deploy.Docker
has been moved to a dedicated plugin called GenieDeployDocker.jl
. This means that all references to Genie.Deploy.Docker
need to be updated to use GenieDeployDocker
. The GenieDeployDocker
plugin is dependent on the GenieDeploy
package and it extends the functionality of GenieDeploy
.
11. Genie.Deploy.Heroku
Starting with Genie 5, the Heroku
deployment functionality provided by Genie.Deploy.Heroku
has been moved to a dedicated plugin called GenieDeployHeroku.jl
. This means that all references to Genie.Deploy.Heroku
need to be updated to use GenieDeployHeroku
. The GenieDeployHeroku
plugin is dependent on the GenieDeploy
package and it extends the functionality of GenieDeploy
.
12. Genie.Deploy.JuliaHub
Starting with Genie 5, the JuliaHub
deployment functionality provided by Genie.Deploy.JuliaHub
has been moved to a dedicated plugin called GenieDeployJuliaHub.jl
. This means that all references to Genie.Deploy.JuliaHub
need to be updated to use GenieDeployJuliaHub
. The GenieDeployJuliaHub
plugin is dependent on the GenieDeploy
package and it extends the functionality of GenieDeploy
.
13. Genie.App
The Genie.App
module has been removed in v5 and its API has been moved to the Genie
module.
14. Genie.AppServer
The Genie.AppServer
module has been renamed to Genie.Server
in v5.
15. Genie.Plugins
Starting with Genie 5, the Genie.Plugins
functionality has been moved to a dedicated plugin called GeniePlugins.jl
. This means that all references to Genie.Plugins
need to be updated to use GeniePlugins
. The GeniePlugins
plugin is dependent on the Genie
package and it extends the functionality of Genie
.
16. Genie.new
family of functions
All the Genie.new
functions have been moved to Genie.Generator
in v5.
17. No automatic import of Genie
in Main
(at REPL)
Genie v4 apps would automatically import Genie
in Main
, so that Genie
would be readily available at the REPL. Starting with Genie 5, this is no longer the case and at the app's REPL it's now necessary to first run julia> using Genie
.
18. Modification of bin/server
and bin/server.bat
The scripts responsible for starting the app in non-interactive/serving mode need to be updated by replacing the end of the command from s "$@"
to -s=true "$@"
.
19. Update config/initializers/logging.jl
Update the content of the logging.jl
initializer to this:
import Genie
Genie.Logger.initialize_logging()
20. Other
Genie 5 also changes or removes other APIs which can be generally be considered as internal. If you find other important breaking changes that have been missed, please open an issue on the Genie GitHub repository or just edit this file and submit a PR.