When looking for a solution to display HTML, execute JavaScript, or use OAuth2 protocol in Java, one often looks for a full-fledged embeddable browser. If you go for Chromium, you can either use JxBrowser or Java Chromium Embedded Framework (JCEF) for integration.

We have gathered the most common comparison points and compiled this guide for you. To help you choose between the libraries, we compare their architecture, functionality, and required integration efforts.

In a nutshell

Being open-source and free, JCEF may be a viable solution for open-source, low-budget, or academic projects.

However, it still comes with maintenance costs. Your development team will need time and expertise to cover what is not covered by the JCEF community:

  • Maintain the build infrastructure for different platforms.
  • Regularly build and package new versions of JCEF.
  • Notarize and sign binaries on macOS and Windows.
  • Fix issues and implement new features.

JxBrowser requires no maintenance. You can start using it in five minutes. The library offers more features and native support for all UI toolkits. And if you lack the feature, found an issue, or have a question, you can always count on our help.

Get a stable and easy-to-use browser for Java
Try for free

Getting started

JCEF is an open-source alternative to JxBrowser. It is based on Chromium Embedded Framework (CEF) and allows you to embed a web browser into Java Swing desktop applications.

To start using JCEF, you need to build it yourself. This process has three parts:

  1. Configure the environment.
  2. Compile binaries and Java classes.
  3. Package it all to JAR and add it to your application.

JxBrowser is a commercial proprietary library. To start using JxBrowser, add a single dependency to your Gradle or Maven app. Or download the library and add JxBrowser to the classpath.

JxBrowser JAR files contain all necessary binaries and require no additional actions from the developers. The binaries for macOS are notarized and the binaries for Windows are signed.

What’s inside

Both JxBrowser and JCEF use Chromium under the hood.

JCEF is built on top of CEF. This is a well-known C++ framework that has bindings for other programming languages too.

JxBrowser uses a proprietary in-house solution for Chromium integration. It is not based on CEF. We’ve been developing it since 2007 and also use it in DotNetBrowser.

Supported UI toolkits

JCEF provides a Swing component. If you develop your application using JavaFX or SWT, you will need to use integration bridges. These are SwingNode for JavaFX, and SWT_AWT bridge for SWT.

JxBrowser provides native components for all major UI toolkits: JavaFX, Swing, and SWT. Check out how to create a simple application using any toolkit in our Quick Start guide.

Our clients also use JxBrowser in Eclipse RCP, IntelliJ IDEA, and NetBeans plug-ins.

Embedding for desktop

The effort required to write a simple desktop application is similar for both libraries. Here is an example with an address bar and the browser:

JCEF
JxBrowser
import org.cef.CefApp;
import org.cef.CefClient;
import org.cef.CefSettings;
import org.cef.browser.CefBrowser;
import org.cef.browser.CefMessageRouter;

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

/**
 * This is a simple application with the address bar and JCEF.
 */
public final class JcefExample {

    private static final String URL = "https://teamdev.com";
    private static final boolean OFFSCREEN = false;
    private static final boolean TRANSPARENT = false;

    public static void main(String[] args) {
        if (!CefApp.startup(args)) {
            System.out.println("Startup initialization failed!");
            return;
        }

        CefSettings settings = new CefSettings();
        settings.windowless_rendering_enabled = OFFSCREEN;
        CefApp cefApp = CefApp.getInstance(settings);
        CefClient client = cefApp.createClient();
        client.addMessageRouter(CefMessageRouter.create());
        CefBrowser browser = client.createBrowser(URL, OFFSCREEN, TRANSPARENT);

        JTextField address = new JTextField(URL);
        address.addActionListener(e -> browser.loadURL(address.getText()));

        JFrame frame = new JFrame("JCEF");
        frame.add(address, BorderLayout.NORTH);
        frame.add(browser.getUIComponent(), BorderLayout.CENTER);
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        frame.setSize(1280, 900);
        frame.setVisible(true);
    }
}
import static com.teamdev.jxbrowser.engine.RenderingMode.HARDWARE_ACCELERATED;

import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.engine.Engine;
import com.teamdev.jxbrowser.view.swing.BrowserView;
import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

/**
 * This is a simple application with the address bar and JxBrowser.
 */
public final class JxBrowserExample {

    private static final String URL = "https://teamdev.com";

    public static void main(String[] args) {
        Engine engine = Engine.newInstance(HARDWARE_ACCELERATED);
        Browser browser = engine.newBrowser();

        SwingUtilities.invokeLater(() -> {
            final BrowserView view = BrowserView.newInstance(browser);

            JTextField address = new JTextField(URL);
            address.addActionListener(e -> browser.navigation().loadUrl(address.getText()));

            JFrame frame = new JFrame("JxBrowser");
            frame.add(address, BorderLayout.NORTH);
            frame.add(view, BorderLayout.CENTER);
            frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            frame.setSize(1280, 900);
            frame.setVisible(true);

            frame.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    engine.close();
                }
            });

            browser.navigation().loadUrl(address.getText());
        });
    }
}

Embedding for headless

If your application runs without UI, JCEF is not for you. It requires a visible Swing UI, otherwise, the browser is not initialized completely.

With JxBrowser, you can create a fully functional browser with a true off-screen rendering. Take a look:

import static com.teamdev.jxbrowser.engine.RenderingMode.OFF_SCREEN;

import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.engine.Engine;
import com.teamdev.jxbrowser.ui.Bitmap;
import com.teamdev.jxbrowser.view.swing.graphics.BitmapImage;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

/**
 * An example of the JxBrowser launched without UI.
 */
public final class ServerApplicationExample {

    public static void main(String[] args) {
        Engine engine = Engine.newInstance(OFF_SCREEN);
        Browser browser = engine.newBrowser();
        browser.resize(1280, 1024);

        browser.navigation().loadUrlAndWait("https://teamdev.com");

        // The browser is up and running. Let's take a screenshot and check.
        Bitmap bitmap = browser.bitmap();
        BufferedImage image = BitmapImage.toToolkit(bitmap);
        try {
            ImageIO.write(image, "PNG", new File("screenshot.png"));
        } catch (IOException e) {
            System.out.println("Failed to save an image. " + e.getMessage());
        }
    }
}

API and features

JCEF provides a variety of features for managing Chromium networking, printing, handling downloads, etc.

With JxBrowser you can do the same and much more. In this section, we demonstrate the features that are not available in JCEF.

Working with DOM

When it comes to DOM, you have the full power of the browser wrapped into a comprehensible Java API. Take a look at this example or check out the guide.

// Find nodes in the DOM tree. By a tag name.
List<Element> links = document.findElementsByTagName("a");
// By a CSS selector.
Optional<Element> logo = document.findElementByCssSelector("#logo");
// Or even through JavaScript.
FormElement form = document.frame().executeJavaScript("document.forms[0]");
// Access the attributes.
links.forEach(link -> link.putAttribute("target", "blank"));
// Submit a form.
form.submit();
// Scroll to the element.
logo.ifPresent(l -> l.scrollIntoView(BOTTOM));

Interaction between JavaScript and Java

Execute JavaScript code from Java, call Java methods from JavaScript. And enjoy the automatic type conversion. Take a look at this example or check out the  guide.

// Obtain objects from JavaScript. As a String.
String string = frame.executeJavaScript("'A string literal'");
// As an array.
JsArray array = frame.executeJavaScript("[0, 1, 2, 3, 4]");
// Or as a generic JavaScript object.
JsObject window = frame.executeJavaScript("window");
// Pass any Java object to the JavaScript world.
window.putProperty("java", new MyJavaObject());

Emulating user input

Reinforce your automated tests and tooling by simulating user interaction. Take a look at the example or check out the guide.

Point rect = buttonElement.boundingClientRect();
Point center = Point.of(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2);
browser.dispatch(MousePressed.newBuilder(location)
                             .button(MouseButton.PRIMARY)
                             .build());
browser.dispatch(MouseReleased.newBuilder(location)
                              .button(MouseButton.PRIMARY)
                              .build());

Proprietary codecs and widevine

The proprietary technologies such as H264 and AAC codecs are disabled by default, but it is very easy to enable them:

EngineOptions options =
        EngineOptions.newBuilder(HARDWARE_ACCELERATED)
                     .enableProprietaryFeature(ProprietaryFeature.AAC)
                     .enableProprietaryFeature(ProprietaryFeature.H_264)
                     .enableProprietaryFeature(ProprietaryFeature.WIDEVINE)
                     .build();
Engine engine = Engine.newInstance(options);

And even more

There are dozens of features that you will find only in JxBrowser. Some of them are:

  • Managing Chromium profiles;
  • Managing passwords;
  • Auto-filling web forms on a web page;
  • The Print Preview dialog;
  • SSO support out of the box;
  • The <datalist> HTML tag in the off-screen rendering mode;
  • Drag-and-drop in the off-screen rendering mode;
  • WebRTC and screen sharing;

and more.

Architecture

The main architectural difference between the libraries is a processing model. JCEF launches Chromium inside the Java process. While JxBrowser launches Chromium in a separate native process.

The JCEF’s model allows you to initialize Chromium faster, but it has major drawbacks:

  • Chromium consumes the memory and CPU of the Java process. The more Chromium instances you create, the more resources are taken from your application.
  • Any error or unexpected behavior in Chromium might cause a JVM crash and terminate your Java application with the potential user data lost.
  • The Java process becomes susceptible to security vulnerabilities in Chromium.

JCEF architecture

JxBrowser runs Chromium in a separate process and communicates with it through the IPC. This way, Chromium does not affect the memory usage of the Java process.

If Chromium crashes, the Java process will continue running. JxBrowser even provides the API to let your application know when Chromium crashes. This gives you the ability to restart the browser and restore a  user session.

JxBrowser architecture

Getting help

JCEF is an open-source project. If you need help, you can ask your question on the forum or create an issue in the bug tracker. If there is a feature you’d like to have, you can contribute.

JxBrowser is a commercial product created for commercial companies. We care about our clients and provide support services. When you contact our technical support, you’ll be talking directly to an engineer that develops the product.

If you see a bug, we’ll fix it and provide you with a preview build right after. If there is a feature missing, we’ll implement it for you and release it in one of the future versions.

For advanced cases and custom requests, we offer premium services.

Updates and release cycle

In 2021, JCEF rolled out five releases. Every new release comes with a Chromium version upgrade. The lack of release notes makes it hard to analyze what else is included in the new version.

JxBrowser had 12 releases in 2021. Every release comes with fixes and improvements that we describe in detail in the Release Notes. We upgrade Chromium to the latest stable version within 3–4 weeks after its official release. These upgrades include the latest security patches and fixed vulnerabilities.