All Downloads are FREE. Search and download functionalities are using the official Maven repository.

templates.docs.miscellaneous.html Maven / Gradle / Ivy

There is a newer version: 0.9.28
Show newest version
{#==========================================
Docs : "Miscellaneous"
==========================================#}

Miscellaneous

{#========================================== Default Configurations ==========================================#}

Default Configurations

To know what are the default Spincast configurations, have a look at the Spincast Config plugin page, which is the default implementation of the "ISpincastConfig" interface. But here are some important ones:

  • getServerHost() : The host/IP the HTTP server will listen on. The default is 0.0.0.0, which means the server will listen on any IP.
  • getHttpServerPort() : The port the server will listen to for HTTP (unsecure) requests. If <= 0, the server won't listen on HTTP requests.
  • getHttpsServerPort() : The port the server will listen to for HTTPS (secure) requests. If <= 0, the server won't listen on HTTPS requests. If you use HTTPS, you also have to provide some extra configurations related to the SSL certificate to use.
  • isDebugEnabled() : If true, a development environment is taken for granted, and internal error messages may be displayed publicly, no cache will be used for the templates, etc. The default is true, so make sure you change this to false before deploying to production!

{#========================================== Templating engine ==========================================#}

Templating engine (view engine)

The templating engine (also called view engine, or template engine), is the component you use to generate dynamic HTML pages. It can be used for other purposes, for example to generate the body of an email when some placeholders have to be replaced in the base template, but its most frequent use is to generate HTML pages.

You can inject the ITemplatingEngine component anywhere you need it, but to generate HTML pages the preferred way is to use the methods provided by the response() add-on, on the request context objects:

public class AppController {

    public void myRouteHandler(IAppRequestContext context) {

        IUser user = getUser();

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("user", user);

        // A template which is on the classpath:
        context.response().sendHtmlTemplate("/templates/user.html",
                                            params);

        // Or, a template which is on the file system:
        context.response().sendHtmlTemplate("/usr/www/myProject/templates/user.html",
                                            false,
                                            SpincastStatics.params("user", user));
    }
}

Explanation :

  • 11 : We use the response() add-on to access the sendHtmlTemplate(...) method. This method takes two parameters: the path to the HTML template to use (listed below) and a set of variables to use to generate the final output. By default, the templating engine will try to find the template file on the classpath.
  • 12 : We pass a user object to the templating engine so it can use it to generate the final HTML. Here, we do so using a classic Map<String, Object> structure (7-8).
  • 15-16 : By passing false as a second parameter to the sendHtmlTemplate(...) method, we can also tell the templating engine to search for the template on the file system, and not on the classpath.
  • 17 : SpincastStatics.params(...) is a utility method provided by Spincast to easily create Map<String, Object> parameters, inline. It is equivalent to creating a new HashMap<String, Object>() as in the first example (7-8).

Here's an example template file which would be on the classpath (for example, at src/resources/templates/user.html, in the project). Note that the syntax used inside your templates depends on the implementation of the templating engine you use! In this example, we use the default implementation, Pebble:

{% verbatim %}

<!doctype html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Test</title>
    </head>
    <body>
        <h1>Hello {{user.name}}!</h1> 
    </body>
</html>
{% endverbatim %}

Finally, note that you can also access the templating engine via its own "templating()" add-on, on the request context objects. This can be useful when you need to generate some dynamic content without sending it as the response for the current request:

public class AppController {

    public void myRouteHandler(IAppRequestContext context) {

        IUser user = getUser();
        
        String emailBody = context.templating().fromTemplate("/templates/email.html", 
                                                             SpincastStatics.params("user", user));
        // Do something with the 'emailBody'...
    }
}

{#========================================== SSL ==========================================#}

Using a SSL certificate (HTTPS)

It is recommended that you serve your application over HTTPS and not HTTP, which is not secure. To achieve that, you need to install a SSL certificate.

If you download the Quick Start application, you will find two files explaining the required procedure:

  • /varia/ssl_certificate_howto/self-signed.txt
    Shows how to use a self-signed certificate, for development purpose.
  • /varia/ssl_certificate_howto/lets-encrypt.txt
    Shows how to use a Let's Encrypt certificate. Let's Encrypt is a provider of free, but totally valid, SSL certificates. Instructions in this file will probably work for certificates obtained from other providers, but we haven't tested it yet.

{#========================================== JsonObject ==========================================#}

JsonObject

The JsonObject (interface IJsonObject) is a class provided by Spincast to mimic a real Json object. It is, essentially, a typed Map<String, Object>. So there is a put(String key, Object value) method, but the getters are typed:

  • String getString(String key)
  • Integer getInteger(String key)
  • IJsonObject getJsonObject(String key)
  • ...

You can create a JsonObject, or a JsonArray, using the IJsonManager component. This component can be injected by Guice, or it can be accessed through the json() add-on:

public void myHandler(IAppRequestContext context) {

    IJsonObject obj = context.json().create();
    obj.put("name", "Stromgol");
    obj.put("lastName", "Laroche");

    context.response().sendJsonObj(obj);
}

Spincast uses JsonObject objects in many places. For example, to get the content of a request for which a Json body has been sent via ajax :

public void myHandler(IAppRequestContext context) {
    IJsonObject json = context.request().getJsonBodyAsJsonObject();
    // ...
}}

Or even when XML is sent :

public void myHandler(IAppRequestContext context) {
    IJsonObject json = context.request().getXmlBodyAsJsonObject();
    // ...
}}

{#========================================== Spincast Utilities ==========================================#}

Spincast Utilities

Spincast provides some generic utilities, accessible via the ISpincastUtils interface:

  • void zipDirectory(File directoryToZip, File targetZipFile, boolean includeDirItself)
    Zips a directory.
    @param targetZipFile the target .zip file. If the parent directories don't exist, tries to create them.
    @param If true, the directory itself will be included in the zip file, otherwise only its content will be.
  • void zipExtract(File zipFile, File targetDir)
    Extracts a .zip file to the specified directory.
    @param targetDir The target directory. If it doesn't exist, tried to create it (and its parents, if required).
  • String getMimeTypeFromPath(String path)
    Gets the mime type from a path, using its extension.
    @return the mime type or null if it can't be decided.
  • String getMimeTypeFromExtension(String extension)
    Gets the mime type from the extension.
    @return the mime type or null if it can't be decided.
  • Locale getLocaleBestMatchFromAcceptLanguageHeader(String acceptLanguageHeader)
    Gets the best Locale to use given a "Accept-Language" HTTP header.
    @return the best Locale to use or null if the given header can't be parsed.
  • boolean isContentTypeToSkipGziping(String contentType)
    Should the specified Content-Type be gzipped?
  • File getAppJarDirectory()
    Returns the working directory: the directory in which the executable .jar is located.
    @return the working directory or null if the application is running inside an IDE.
  • String getSpincastCurrentVersion()
    Gets the current Spincast version.

{#========================================== @MainArgs ==========================================#}

@MainArgs

Both SpincastCoreGuiceModule and SpincastDefaultGuiceModule Guice modules have a constructor which accepts String[] mainArgs. You can pass to it the arguments received in your main(...) method. For example:

public static void main(String[] args) {

    Injector guice = Guice.createInjector(new SpincastDefaultGuiceModule(args));

    App app = guice.getInstance(App.class);
    app.start();
}

By doing so, those arguments will be bound, using a @MainArgs annotation. You can then inject them anywhere you need:

public class AppConfig extends SpincastConfig implements IAppConfig {

    private final String[] mainArgs;

    @Inject
    public AppConfig(@MainArgs String[] mainArgs) {
        this.mainArgs = mainArgs;
    }

    protected String[] getMainArgs() {
        return this.mainArgs;
    }

    @Override
    public int getHttpServerPort() {

        int port = super.getHttpServerPort();
        if(getMainArgs().length > 0) {
            port = Integer.parseInt(getMainArgs()[0]);
        }
        return port;
    }
}

{#========================================== Using an init() method ==========================================#}

Using an init() method

This is more about standard Guice development than about Spincast, but we feel it's a useful thing to know.

Guice doesn't provide support for a @PostConstruct annotation out of the box. And since it is often seen as a bad practice to do too much work directly in a constructor, what we want is an init() method to be called once the object it fully constructed, and do the initialization work there.

The trick is that Guice calls any @Inject annotated methods once the object is created, so let's use this to our advantage:

public class UserService implements IUserService {

    private final ISpincastConfig spincastConfig;

    @Inject
    public UserService(ISpincastConfig spincastConfig) {
        this.spincastConfig = spincastConfig;
    }

    @Inject
    protected void init() {
        doSomeValidation();
        doSomeInitialization();
    }

    //...
}

Explanation :

  • 5-8 : The constructor's job is only to receive the dependencies.
  • 10-14 : An init() method is also annotated with @Inject. This method will be called once the object is fully constructed. This is a good place to do some initialization work!

What we recommend is constructor injection + one (and only one) @Inject annotated method. The problem with multiple @Inject annotated methods (other than constructors) is that it's hard to know in which order they will be called.

Finally, if the init() method must be called as soon as the application starts, make sure you bind the object using asEagerSingleton()!





© 2015 - 2025 Weber Informatics LLC | Privacy Policy