Skip to content

SØAD Framework Components

Transaction: The Controller Layer

Transactions in SØAD act as the primary entry point for executing business logic in response to a URL request. Each transaction is mapped to a URL using a structured convention:

/t/{group}/{code}/{action}
  • Group: A logical folder that represents a module or feature set, used to organize related transactions (e.g., web, admin, user).
  • Code: The transaction identifier, which corresponds to the .py file and class name (e.g., home maps to home.py and Home class).

For instance, the URL /t/web/home translates to:

  • web as the group (folder)
  • home as the code (Python file and class name)
  • view() as the default method executed, unless an alternative action is specified

This pattern keeps your codebase modular and consistent, supporting better project organization as your application grows.

When a client sends a request such as /t/web/home/view, the framework handles it through the following flow:

"Transaction Flow"

SØAD Transaction Flow

  1. Start a Database Transaction – The framework initiates a connection using ActiveJDBC's Base.openTransaction(). This ensures all operations are enclosed in a database transaction.
  2. Locate the Transaction Class – The request is mapped to a specific Jython file and class. For example, /t/web/home/view maps to web/home.py, class Home, method view().
  3. Execute Transaction Logic – The defined method (view(ctx) or any other action) is executed.
  4. Exception Handling – If any exception is thrown during execution, the framework performs a rollback using Base.rollbackTransaction() to ensure no partial writes corrupt the database.
  5. Commit and Close – If execution completes without exception, changes are committed using Base.commitTransaction() and the connection is closed with Base.close().

This transactional structure ensures data integrity and reduces boilerplate error-handling code for developers.

Finally, the transaction method defines how the response should be returned to the client. This is done by setting ctx.go_to to a render method, which determines the output format—typically an HTML view or JSON response.

Example:

URL: /t/web/home

File: web/home.py

from utils import render

class Home(Layout):
    def __init__(self):
        pass

    def view(self, ctx):
        ctx.go_to = render.as_view(ctx, "home")

This Transaction maps directly to the folder structure:

  • Python file: web/home.py
  • HTML template: web/_home/home.html

Convention:

  • Transaction Class: Class name = code name (capitalized)
  • Action Method: Any method in the class (e.g., view, submit, register)
  • Default Method: view() is called if no action is specified in URL

View (HTML) example:

<!doctype html>
<html>
<body>
    <h1>Registration Form</h1>
    <form action="/t/web/home/register" method="post">
        <input type="text" name="email" />
        <button type="submit">Register</button>
    </form>
</body>
</html>

In this example, submit button will invoke register(ctx) method in Home class.

In SØAD, all methods defined inside a Transaction class are treated as actions, which can be invoked directly through corresponding URLs.

Each action method must include the ctx parameter. The framework automatically calls the specified method and injects the current WebContext object, allowing your transaction to handle requests with full access to parameters, session, and others (e.g. HTTP Request & Response).

Transaction Folder Structure

web/
  home.py
  _home/
    home.html
  • .py file handles logic
  • Folder prefixed with _ holds the view templates
  • The main view file must match the transaction name

In addition to the default view, each transaction can define and render multiple views. For example, a Person transaction might have:

web/
  person.py
  _person/
    person.html     (default view for `view()`)
    add.html        (additional view to display new form)
    edit.html       (additional view to display edit form)

Each method can explicitly render its corresponding template using:

ctx.go_to = render.as_view(ctx, "add")

This approach makes it easy to organize multiple page variations under the same transaction and supports clean separation of logic and presentation.

Routing

SØAD routes every request through a clean, convention-based URL structure to the Transaction:

/t/{group}/{code}/{action}
  • /t — transaction prefix
  • {group} — folder/module name
  • {code} — transaction file/class
  • {action} — method inside the class; defaults to view

Example URL Mapping:

  • /t/base/login → calls Login.view()
  • /t/web/home/register → calls Home.register()
  • /t/app/user/edit?user_id=5 → calls User.edit() with query param

Context Path

In Java Servlet architecture, the context path refers to the root path of a deployed web application. It is the prefix added to all URLs served by the application.

In SØAD Framework, the context path can be retrieved within a transaction using:

ctx.ctxPath

By default, SØAD assumes the context path is an empty string ("") when running as a standalone application. However, if the application is deployed with a context (for example, under /myapp), then this value will reflect that path.

Example:

Given a deployed application URL:

https://www.sufia.online/myapp/t/web/welcome
  • Context Path: /myapp
  • Transaction URL: /t/web/welcome

This context path is useful when constructing links or redirecting within views and templates to ensure consistency across environments.


View

Each transaction ends by setting ctx.go_to to a function that define the response. The most common output is an HTML page rendered using the render.as_view() function:

ctx.go_to = render.as_view(ctx, "home")

This will render the home.html view inside the _home folder.

Note

The ctx.go_to parameter can accept either a string or a function. When a string is provided, it is treated as a URL path, and the framework redirects the user to that URL using response.sendRedirect(). If a function is provided, it is executed, and its output is returned to the user. The function is responsible for processing the response, including setting the content type, status code, and writing the response body to the HttpServletResponse object.

View Files

Views in SØAD are typically HTML files enhanced with Handlebars syntax. Handlebars allows dynamic content rendering by using placeholders and control logic directly within the HTML.

You can:

  • Insert variables: {{user_name}}
  • Perform loops: {{#each items}}...{{/each}}
  • Add conditions: {{#if isAdmin}}...{{else}}...{{/if}}
  • Use helpers: such as select, dateFmt, or ref_lookup

This makes the HTML highly flexible and data-driven while remaining clean and readable.

Output Render Methods

SØAD provides multiple output render methods through utils.render:

  • render.as_view(ctx, view) - Render Handlebars HTML
  • render.as_json(ctx, obj) - Render JSON
  • render.as_html(ctx, code) - Raw HTML
  • render.as_string(ctx, text) - Plain string
  • render.as_file(ctx, file) - File download
  • render.as_blob(ctx, blob) - Binary data
  • render.as_pdf(ctx, view) - PDF output

You can find examples of how to use these render functions in the Code Library section of this documentation.

handlebars helpers

Handlebars supports built-in helpers and custom helpers for advanced functionality. You can use these helpers to manipulate data, format output, and control rendering logic directly within your templates.

Built-in helpers:

  • if, else, unless, each, and, or, not, eq

Custom helpers:

  • ref_lookup
  • select, option
  • dateFmt
  • in
  • html
  • session
  • get

You can find more details about these helpers in the Utilities chapter of this documentation.


Model

In SØAD Framework, Model classes are automatically generated from the database tables using ActiveJDBC. Once generated, these classes are automatically instrumented.

Instrumentation in ActiveJDBC refers to the process of enhancing the compiled Java Model classes so they are ActiveJDBC-aware. This means they gain access to methods such as saveIt(), findAll(), first(), where(), and many others provided by the ActiveJDBC framework.

SØAD handles this behind the scenes. At runtime, after introspecting the database schema and generating the Model classes, the framework runs ActiveJDBC’s instrumentation process to inject the necessary metadata and behaviors. This allows you to interact with your database tables as if they were regular Java classes, making CRUD operations straightforward and intuitive.

Given a person table:

package models;

import org.javalite.activejdbc.Model;

public class Person extends Model {}

Usage in Transaction:

from models import Person

class Home(Layout):
    def view(self, ctx):
        persons = Person.findAll()
        ctx.output["all_person"] = persons
        ctx.go_to = render.as_view(ctx, "home")

Example: Hello World

Folder structure:

web/
  hello.py
  _hello/
    hello.html

hello.py

from utils import render

class Hello(Layout):
    def view(self, ctx):
        ctx.go_to = render.as_view(ctx, "hello")

_hello/hello.html

<!doctype html>
<html>
<body>
    <h1>Hello, SØAD</h1>
</body>
</html>