-
Couldn't load subscription status.
- Fork 161
admin console faces tutorial.adoc
- 1. Introduction
- 2. Functional example
- 3. Prerequisites
- 4. Overview
-
5. Step-by-Step Implementation
- 5.1. Step 1: Create the Plugin Module Structure
- 5.2. Step 2: Create the Maven POM
- 5.3. Step 3: Create the CDI Bean
- 5.4. Step 4: Create the Console Plugin Service
- 5.5. Step 5: Configure the Console Integration
- 5.6. Step 6: Create the Navigation Node Template
- 5.7. Step 7: Create the JSF Page
- 5.8. Step 8: Update Build Configuration
- 5.9. Step 9: Build and Test
- 6. Architecture Overview
- 7. Advanced Features
- 8. Troubleshooting
- 9. Conclusion
This tutorial demonstrates how to create a new Jakarta Faces (JSF) page in the GlassFish Admin Console and integrate it into the sidebar navigation. The example creates a "Hello World" page that displays a message retrieved from a CDI bean.
For a complete functioning example, see the example_admin-console-faces-plugin branch in GlassFish repository.
-
GlassFish 7.x source code
-
Maven 3.9.0+
-
JDK 17+
-
Basic knowledge of Jakarta Faces and CDI
The GlassFish Admin Console supports two types of pages:
-
JSF-templating pages (
.jsffiles) - Legacy templating system -
Jakarta Faces pages (
.xhtmlfiles) - Modern JSF pages (NEW)
This tutorial focuses on creating modern Jakarta Faces pages that can be integrated into the existing console.
Create a new Maven module for your console plugin:
mkdir -p appserver/admingui/hello-world/src/main/java/org/glassfish/helloworld/admingui
mkdir -p appserver/admingui/hello-world/src/main/resources/META-INF/{admingui,resources/helloworld}Create appserver/admingui/hello-world/pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.glassfish.main.admingui</groupId>
<artifactId>admingui</artifactId>
<version>7.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>console-hello-world-plugin</artifactId>
<packaging>glassfish-jar</packaging>
<name>Admin Console Hello World Plugin</name>
<description>Hello World plugin example for GlassFish Admin Console</description>
<dependencies>
<dependency>
<groupId>jakarta.enterprise</groupId>
<artifactId>jakarta.enterprise.cdi-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.main.admingui</groupId>
<artifactId>console-common</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>Create src/main/java/org/glassfish/helloworld/admingui/HelloWorldBean.java:
package org.glassfish.helloworld.admingui;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Named;
@Named
@RequestScoped
public class HelloWorldBean {
public String getMessage() {
return "Hello World from GlassFish Admin Console!";
}
public String getDescription() {
return "This is a JSF page created using Jakarta Faces in the GlassFish Admin Console.";
}
}Create src/main/java/org/glassfish/helloworld/admingui/HelloWorldConsolePlugin.java:
package org.glassfish.helloworld.admingui;
import java.net.URL;
import org.glassfish.api.admingui.ConsoleProvider;
import org.jvnet.hk2.annotations.Service;
@Service
public class HelloWorldConsolePlugin implements ConsoleProvider {
@Override
public URL getConfiguration() {
return null; // Uses default META-INF/admingui/console-config.xml
}
}Create src/main/resources/META-INF/admingui/console-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<console-config id="helloworld">
<integration-point
id="helloworld_nav_node"
type="org.glassfish.admingui:navNode"
priority="100"
parentId="tree"
content="navigation/helloWorldNavNode.jsf"
/>
</console-config>Key Configuration Elements:
-
type="org.glassfish.admingui:navNode"- Adds a navigation node to the sidebar -
priority="100"- Controls the order in the navigation (lower = higher in the list) -
parentId="tree"- Adds to the main navigation tree -
content- Points to the JSF template that defines the navigation node
Create src/main/resources/META-INF/resources/helloworld/navigation/helloWorldNavNode.jsf:
<sun:treeNode id="helloWorldNode"
text="Hello World"
url="/helloworld/hello.xhtml"
imageURL="/resource/images/instance.gif"
target="main"
/>Template Attributes:
-
text- Display name in the sidebar -
url- Target JSF page (.xhtmlextension for Jakarta Faces) -
imageURL- Icon displayed next to the navigation item -
target="main"- Opens in the main content area
Create src/main/resources/META-INF/resources/helloworld/hello.xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="jakarta.faces.html"
xmlns:f="jakarta.faces.core">
<h:head>
<title>Hello World - GlassFish Admin Console</title>
<!-- Include GlassFish Admin Console CSS -->
<link rel="stylesheet" type="text/css"
href="#{request.contextPath}/theme/com/sun/webui/jsf/suntheme/css/css_master.css"/>
<link rel="stylesheet" type="text/css"
href="#{request.contextPath}/resource/common/css/style.css"/>
<style type="text/css">
.hello-container {
padding: 20px;
margin: 20px;
background-color: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 5px;
}
.hello-title {
color: #2c5aa0;
font-size: 24px;
font-weight: bold;
margin-bottom: 15px;
}
</style>
</h:head>
<h:body>
<div class="hello-container">
<div class="hello-title">
<h:outputText value="GlassFish Admin Console JSF Example"/>
</div>
<div>
<h:outputText value="#{helloWorldBean.message}"/>
</div>
<div>
<h:outputText value="#{helloWorldBean.description}"/>
</div>
<br/>
<h:form>
<h:commandButton value="Refresh Page"
action="#{null}"
styleClass="Btn1"/>
</h:form>
</div>
</h:body>
</html>Key JSF Features:
-
Standard Jakarta Faces XHTML template
-
CDI bean access via
#{helloWorldBean.message} -
GlassFish console CSS integration
-
JSF form components (
h:form,h:commandButton)
Add the new module to appserver/admingui/pom.xml:
<modules>
<!-- existing modules -->
<module>commandrecorder</module>
<module>hello-world</module> <!-- ADD THIS LINE -->
<module>community-theme</module>
<!-- remaining modules -->
</modules>Add the plugin dependency to appserver/admingui/war/pom.xml:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>console-hello-world-plugin</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>Build GlassFish with the new plugin:
mvn clean install -PfastStart GlassFish and access the Admin Console:
./appserver/distributions/glassfish/target/stage/glassfish7/bin/asadmin start-domainNavigate to http://localhost:4848 and look for "Hello World" in the sidebar navigation.
-
Plugin Discovery: The
HelloWorldConsolePluginservice is discovered by HK2 -
Configuration Loading: The
console-config.xmlis loaded and parsed -
Integration Points: Navigation nodes are registered with the console framework
-
Resource Loading: JSF pages and resources are loaded from
META-INF/resources/ -
CDI Integration: Beans are available in JSF pages via standard EL expressions
hello-world/
├── pom.xml
├── src/main/java/
│ └── org/glassfish/helloworld/admingui/
│ ├── HelloWorldBean.java # CDI Bean
│ └── HelloWorldConsolePlugin.java # HK2 Service
└── src/main/resources/
└── META-INF/
├── admingui/
│ └── console-config.xml # Plugin Configuration
└── resources/helloworld/
├── hello.xhtml # Main JSF Page
└── navigation/
└── helloWorldNavNode.jsf # Navigation Template
You can inject GlassFish services into your CDI beans using HK2 producers:
@ApplicationScoped
public class ServiceProducer {
@Produces
CommandRunner getCommandRunner() {
return Globals.getDefaultHabitat().getService(CommandRunner.class);
}
}Access user information via Jakarta Security:
@Inject
SecurityContext securityContext;
public String getCurrentUser() {
return securityContext.getCallerPrincipal().getName();
}-
Page not found: Ensure the URL in the navigation node matches the XHTML file location
-
CDI bean not found: Verify the bean is
@Namedand in the correct package -
Navigation not appearing: Check the console-config.xml syntax and integration point type
-
CSS not loading: Verify the CSS paths in the XHTML head section
This tutorial demonstrated how to create a modern Jakarta Faces page integrated into the GlassFish Admin Console. The approach provides:
-
Modern JSF Development - Use standard Jakarta Faces instead of legacy templating
-
CDI Integration - Full dependency injection support
-
Modular Architecture - Plugin-based approach for maintainability
-
Console Integration - Seamless integration with existing navigation and styling
The example can be extended to create complex administrative interfaces while maintaining consistency with the existing GlassFish Admin Console design and functionality.