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 file src/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.