Interoperability with Java

October 24, 2024

Interoperability with Java components & services for existing users

Thanks to GraalVM, it is entirely possible for JavaScript code to access Java libraries and services directly without needing to go through layers such as HTTP requests. Java objects may be exposed by the server to make them available to JavaScript/JSX code, as is the case with the useServerContext that exposes the following structure :

/**
 * A context object that gives access to the underlying Jahia Java objects that are part of the current rendering context
 */
export interface ServerContext {
    /**
     * Jahia's rendering context, it provides access to all kinds of context information, such as the current request, response, user, mode, mainResource and more
     */
    renderContext : RenderContext;
    /**
     * The current resource being rendered, which is a combination of the current node and its template/view information
     */
    currentResource : Resource;
    /**
     * The current JCR node being rendered
     */
    currentNode : JCRNodeWrapper;
    /**
     * The main JCR node being rendered, which is the root node of the current page
     */
    mainNode : JCRNodeWrapper;
    /**
     * The OSGi bundle key of the current module being rendered
     */
    bundleKey : string;
}

    

All the types in the interface are actually Java classes exposed through the useServerContext() hook to be accessible in React components. This makes it possible to access all the power of Jahia’s API while still remaining inside the JavaScript/React development environment. There are other Java objects and functions available through the server object.

Be careful when calling Java code

It is important to note that only the documented objects are considered supported. All other objects that might be accessible, for example using Java.type() to access other Jahia classes is not supported and these may be deprecated, removed, or modified at any time, so it is recommended to avoid using them. If there are objects that you believe Jahia should expose, please open a ticket with Jahia support team to inform us of your requirements.

Also, it is generally recommended to minimize the number of calls to Java code and to build as much as possible in JavaScript.

Java Interoperability Q&A

In this section, we will answer some common questions that users might have about JavaScript modules.

Can I add JSP in JavaScript module ?

No this will not work. While the system will detect the JSP files, they will require OSGi imports in the MANIFEST.MF file that are generated by the Jahia Maven Plugin that is not used when building JavaScript modules. Anyway this would never be recommended as the JavaScript modules are designed to fully replace all the needs for JSP, including replacing the functionality of tag libraries with custom React components.

Can I add JSX views to my Java modules?

This is technically possible although not easy, but it is not recommended at all. It is much better to create a separate module that will for example access some functionality provided by a Java module.

Can I mix JavaScript modules and Java on the same website?

Yes, mixing JavaScript and Java modules is fully supported on the same website and is a very common deployment scenario for users who are upgrading from previous versions. It is also possible to use elements registered by one type of module in the other type, for example, using content definitions or Java services. For new projects, it is, however, recommended to choose between JavaScript modules and Java modules and ideally use one type of module to simplify project maintenance.

On the same page?

Yes it is possible to use JavaScript and Java modules on the same page, this is a supported scenario. The same recommendation as in the case of website applies, avoid mixing the two types if possible, to make maintenance of the modules easier.

Comparing React server-side and client-side components

React offers two main approaches to rendering: client-side rendering (CSR) and server-side rendering (SSR). Each method has its own advantages and considerations.

Client-Side Rendering (CSR)

In CSR, the entire React application is loaded in the browser. This means that the initial page load is faster because only minimal HTML is sent from the server. Once the initial HTML is loaded, the JavaScript bundle containing the React components is fetched and executed, allowing the application to render and function dynamically. CSR is ideal for applications where interactivity and real-time updates are essential, such as single-page applications (SPAs).

Server-Side Rendering (SSR)

In SSR, the React components are rendered on the server into HTML before being sent to the client's browser. This means that the user receives a fully rendered page directly from the server, which can improve performance, especially in scenarios where search engine optimization (SEO) or initial page load speed is crucial. SSR can also enhance perceived performance by providing meaningful content to users more quickly.

Hooks and Components Not Compatible with SSR

While most React features work seamlessly in both CSR and SSR, there are some hooks and components that are not compatible with server-side rendering. This is because SSR requires rendering on the server, where certain browser-specific APIs and lifecycle methods are unavailable. Some examples of hooks and components that may not work properly or cause issues in SSR include:

  • Window and Document Hooks: Hooks like useEffect or useState that rely on browser-specific objects such as window or document may not work as expected in SSR because these objects are not available on the server.
  • Lifecycle Methods: Class-based lifecycle methods like componentDidMount or componentDidUpdate do not exist in functional components and are not supported in SSR.
  • Third-party Libraries: Some third-party libraries may rely on browser APIs and may not be compatible with SSR out of the box. Developers need to ensure that any libraries they use are SSR-compatible or provide SSR-specific implementations.

Reusing React components between CSR and SSR

Building React components that can be used both in client-side rendering (CSR) and server-side rendering (SSR) involves considering the differences between these rendering environments and writing components that are compatible with both.

Here's a guide on how to build such components:

  • Avoid Browser-Specific Code: Write components that do not rely on browser-specific objects or APIs, such as window, document, or localStorage. Instead, use feature detection or provide alternative implementations where necessary.
  • Stateless components: as much as possible prefer stateless to stateful components when developing components that must work in both environments, as they are simpler and will therefore be easier to get to work everywhere.
  • Conditional Rendering: Use conditional rendering to handle cases where certain features or behaviors are not available in SSR. You can conditionally render components, features, or data based on the environment using techniques like ternary operators or logical && operators.
  • Test in Both Environments: Test your components thoroughly in both CSR and SSR environments to ensure they behave as expected and handle edge cases gracefully. Tools like Jest and Enzyme can help with testing React components.

Benefits of building components that work in both CSR and SSR include:

  • Reusability: components that can be reused in both environments will prove useful over time to simplify development and maintenance.
  • Skills: The difference between CSR and SSR is small, so developers skilled in one environment will be capable of working on both.
  • Packaging: It is possible to build libraries that work in both environments, managing the lifecycle of these libraries separately from the components that use them, easing development, testing, and deployment.