ASP.NET Web Forms is probably the most well-known component style web application framework.
| Name and creator | ASP.NET Web Forms / Microsoft |
| History | Version 1.0 in 2002 Version 2.0 in 2005 |
| Programming language | C# or VB.NET |
| View technology | ASPX |
| Deployment | IIS |
| Other technical characteristics | |
| Status | Somewhat obsolete with the introduction of ASP.NET MVC in 2009 Truly obsolete when not included in .NET 5.0 in 2020 |
An ASP.NET Web Forms application consist of an ASPX file with markup annd a code behind file in either C# or VB.NET.
The code behind get compiled normally. The ASPX get translated into C#/VB.NET code that inherits from the code behind class and then that get compiled.
index.aspx:
<%@ Page Language="C#" Inherits="Demo.Test" %>
<html>
<head>
<title>ASP.NET Web Forms</title>
</head>
<body>
<h1>ASP.NET Web Forms</h1>
<form runat="server">
<h2>Show data (ListView):</h2>
<asp:ListView id="Data1" runat="server">
<LayoutTemplate>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<tr runat="server" id="itemPlaceholder"/>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr runat="server">
<td><%# Eval("F1") %></td>
<td><%# Eval("F2") %></td>
<td><%# Eval("F3") %></td>
</tr>
</ItemTemplate>
</asp:ListView>
<h2>Show data (Repeater):</h2>
<table border='1'>
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<asp:Repeater id="Data2" runat="server">
<ItemTemplate>
<tr runat="server">
<td><%# Eval("F1") %></td>
<td><%# Eval("F2") %></td>
<td><%# Eval("F3") %></td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
<h2>Add data:</h2>
F1: <asp:TextBox id="F1" runat="server"/>
<br/>
F2: <asp:TextBox id="F2" runat="server"/>
<br/>
F3: <asp:DropDownList id="F3" runat="server"/>
<br/>
<asp:Button id="Save" text="Add" onclick="Save_Click" runat="server"/>
</form>
</body>
</html>
index.cs (code behind):
using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Demo
{
public class Test : Page
{
// components
protected ListView Data1;
protected Repeater Data2;
protected TextBox F1;
protected TextBox F2;
protected DropDownList F3;
protected Button Save;
// bind all data for show
private void BindShowData()
{
Data1.DataSource = DB.GetAll();
Data1.DataBind();
Data2.DataSource = DB.GetAll();
Data2.DataBind();
}
// setup page
public void Page_Load(Object src, EventArgs e)
{
if (!IsPostBack)
{
F3.DataSource = new string[] { "", T1.VER, T1.NOTVER };
F3.DataBind();
}
BindShowData();
}
// form submit
public void Save_Click(object sender, EventArgs e)
{
DB.SaveOne(new T1 { F1 = int.Parse(F1.Text), F2 = F2.Text, F3 = F3.Text });
BindShowData();
}
}
}
DB.cs (simulated database):
using System;
using System.Collections.Generic;
namespace Demo
{
// data class (row in database)
public class T1
{
public const String VER = "Verified";
public const String NOTVER = "Not verified";
public int F1 { get; set; }
public string F2 { get; set; }
public string F3 { get; set; }
}
// simulated database
public class DB
{
private static IList<T1> db;
static DB()
{
db = new List<T1>();
db.Add(new T1 { F1 = 1, F2 = "A", F3 = T1.VER });
db.Add(new T1 { F1 = 2, F2 = "BB", F3 = T1.VER });
db.Add(new T1 { F1 = 3, F2 = "CCC", F3 = T1.VER });
db.Add(new T1 { F1 = 4, F2 = "DDDD", F3 = T1.VER });
db.Add(new T1 { F1 = 5, F2 = "EEEEE", F3 = T1.NOTVER });
}
public static IList<T1> GetAll()
{
return db;
}
public static void SaveOne(T1 o)
{
db.Add(o);
}
}
}
For the .cs files either the source should be placed in App_Code dir or a build assembly should be placed in bin dir.
Nothing is needed in web.config for ASP.NET Web Forms. But for convenience this example use:
<system.webServer>
<defaultDocument enabled="true">
<files>
<add value="index.aspx" />
</files>
</defaultDocument>
</system.webServer>
The result looks like:
index.aspx:
<%@ Page Language="VB" Inherits="Demo.Test" %>
<html>
<head>
<title>ASP.NET Web Forms (VB.NET)</title>
</head>
<body>
<h1>ASP.NET Web Forms (VB.NET)</h1>
<form runat="server">
<h2>Show data (ListView):</h2>
<asp:ListView id="Data1" runat="server">
<LayoutTemplate>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<tr runat="server" id="itemPlaceholder"/>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr runat="server">
<td><%# Eval("F1") %></td>
<td><%# Eval("F2") %></td>
<td><%# Eval("F3") %></td>
</tr>
</ItemTemplate>
</asp:ListView>
<h2>Show data (Repeater):</h2>
<table border='1'>
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<asp:Repeater id="Data2" runat="server">
<ItemTemplate>
<tr runat="server">
<td><%# Eval("F1") %></td>
<td><%# Eval("F2") %></td>
<td><%# Eval("F3") %></td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
<h2>Add data:</h2>
F1: <asp:TextBox id="F1" runat="server"/>
<br/>
F2: <asp:TextBox id="F2" runat="server"/>
<br/>
F3: <asp:DropDownList id="F3" runat="server"/>
<br/>
<asp:Button id="Save" text="Add" onclick="Save_Click" runat="server"/>
</form>
</body>
</html>
index.vb (code behind):
Imports System
Imports System.Collections.Generic
Imports System.Web.UI
Imports System.Web.UI.WebControls
Namespace Demo
Public Class Test
Inherits Page
' components
Protected Data1 As ListView
Protected Data2 As Repeater
Protected F1 As TextBox
Protected F2 As TextBox
Protected F3 As DropDownList
Protected Save As Button
' bind all data for show
Private Sub BindShowData()
Data1.DataSource = DB.GetAll()
Data1.DataBind()
Data2.DataSource = DB.GetAll()
Data2.DataBind()
End Sub
' setup page
Public Sub Page_Load(src As [Object], e As EventArgs)
If Not IsPostBack Then
F3.DataSource = New String() {"", T1.VER, T1.NOTVER}
F3.DataBind()
End If
BindShowData()
End Sub
' form submit
Public Sub Save_Click(sender As Object, e As EventArgs)
DB.SaveOne(New T1() With { _
.F1 = Integer.Parse(F1.Text), _
.F2 = F2.Text, _
.F3 = F3.Text _
})
BindShowData()
End Sub
End Class
End Namespace
DB.vb (simulated database):
Imports System
Imports System.Collections.Generic
Namespace Demo
' data class (row in database)
Public Class T1
Public Const VER As String = "Verified"
Public Const NOTVER As String = "Not verified"
Public Property F1() As Integer
Public Property F2() As String
Public Property F3() As String
End Class
' simulated database
Public Class DB
Private Shared db As IList(Of T1)
Shared Sub New()
db = New List(Of T1)()
db.Add(New T1() With { _
.F1 = 1, _
.F2 = "A", _
.F3 = T1.VER _
})
db.Add(New T1() With { _
.F1 = 2, _
.F2 = "BB", _
.F3 = T1.VER _
})
db.Add(New T1() With { _
.F1 = 3, _
.F2 = "CCC", _
.F3 = T1.VER _
})
db.Add(New T1() With { _
.F1 = 4, _
.F2 = "DDDD", _
.F3 = T1.VER _
})
db.Add(New T1() With { _
.F1 = 5, _
.F2 = "EEEEE", _
.F3 = T1.NOTVER _
})
End Sub
Public Shared Function GetAll() As IList(Of T1)
Return db
End Function
Public Shared Sub SaveOne(o As T1)
db.Add(o)
End Sub
End Class
End Namespace
For the .vb files either the source should be placed in App_Code dir or a build assembly should be placed in bin dir.
Nothing is needed in web.config for ASP.NET Web Forms. But for convenience this example use:
<system.webServer>
<defaultDocument enabled="true">
<files>
<add value="index.aspx" />
</files>
</defaultDocument>
</system.webServer>
The result looks like:
Blazor is a new Microsoft web technology.
Actually Blazor exist in several flavors including Blazor Server and Blazor WebAssembly.
Here we will focus on Blazor Server.
| Name and creator | ASP.NET Core Blazor Server / Microsoft |
| History | First released with .NET Core 3.0 in 2019 |
| Programming language | C# |
| View technology | Razor |
| Deployment | ASP.NET Core Kestrel engine |
| Other technical characteristics | Blazor automatically use CSS and JavaScript so look and feel is not "plain HTML" |
| Status | New technology and not widely used yet |
In Blazor everything is in the Razor file both HTML markup and C#.
index.razor:
@page "/"
<html>
<head>
<title>Blazor</title>
</head>
<body>
<h1>Blazor</h1>
<h2>Show data:</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
@foreach (var o in data)
{
<tr>
<td>@o.F1</td>
<td>@o.F2</td>
<td>@o.F3</td>
</tr>
}
</table>
<h2>Add data:</h2>
<EditForm Model="@o" OnSubmit="@Save">
<label for="f1">F1:</label><InputText id="f1" @bind-Value="o.F1"/>
<br/>
<label for="f2">F2:</label><InputText id="f2" @bind-Value="o.F2"/>
<br/>
<label for="f3">F3:</label><select id="f3" @bind="o.F3">
@foreach(var opt in options)
{
<option value="@opt">@opt</option>
}
</select>
<br/>
<button type="submit">Add</button>
</EditForm>
</body>
</html>
@code
{
// class for add data
private class FormData
{
public string F1 { get; set; }
public string F2 { get; set; }
public string F3 { get; set; }
}
// options
private String[] options = { "", T1.VER, T1.NOTVER };
// data to show
private IList<T1> data = DB.GetAll();
// data to add
private FormData o = new FormData { F1 = "", F2 = "", F3 = "" };
// form submit
private void Save()
{
DB.SaveOne(new T1 { F1 = int.Parse(o.F1), F2 = o.F2, F3 = o.F3 });
}
}
DB.cs (simulated database):
using System;
using System.Collections.Generic;
namespace Demo
{
// data class (row in database)
public class T1
{
public const String VER = "Verified";
public const String NOTVER = "Not verified";
public int F1 { get; set; }
public string F2 { get; set; }
public string F3 { get; set; }
}
// simulated database
public class DB
{
private static IList<T1> db;
static DB()
{
db = new List<T1>();
db.Add(new T1 { F1 = 1, F2 = "A", F3 = T1.VER });
db.Add(new T1 { F1 = 2, F2 = "BB", F3 = T1.VER });
db.Add(new T1 { F1 = 3, F2 = "CCC", F3 = T1.VER });
db.Add(new T1 { F1 = 4, F2 = "DDDD", F3 = T1.VER });
db.Add(new T1 { F1 = 5, F2 = "EEEEE", F3 = T1.NOTVER });
}
public static IList<T1> GetAll()
{
return db;
}
public static void SaveOne(T1 o)
{
db.Add(o);
}
}
}
program.cs (the main program with the embedded web server):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
namespace Demo
{
public class Program
{
public static void Main(string[] args)
{
// start Kestrel with Startup config
Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(b =>
{
b.UseStartup<Startup>();
}).Build().Run();
}
}
// define razor and server size blazor
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration cfg)
{
Configuration = cfg;
}
public void ConfigureServices(IServiceCollection svc)
{
svc.AddRazorPages();
svc.AddServerSideBlazor();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(ep =>
{
ep.MapBlazorHub();
ep.MapFallbackToPage("/_Host");
});
}
}
}
An ASP.NET Core Blazor Server project can be created command line with:
dotnet new blazorserver
The result looks like:
JSF (Java Server Faces) is the Java worlds version of component style web application framnework.
JSF is really a standard and not a product. There are multiple JSF implementations.
Implementations include Mojarra and Apache MyFaces.
There is a complete article dedicated to JSF here.
| Name and creator | JSF / Java EE standard |
| History | Version 1.0 in 2004 Version 1.2 in 2006 Version 2.0 in 2010 Version 3.0 in 2020 rename to JSF (Jakarta Server Faces) Version 4.0 in 2022 rename to JF (Jakarta Faces) |
| Programming language | Java |
| View technology | JSP Facelet |
| Deployment | Servlet container |
| Other technical characteristics | |
| Status | Actively maintained but limited usage today |
JSF is a complicated technology.
The code is in Java classes called backing beans or managed beans. And the view is separate. But there is no simple relationship between view and backing bean. Backing beans just exist in the web application.
Furthermore lots of configuration required (web application, JSF, CDI etc.).
And there are different choices for view technology including:
But first the non-view part that is common for all views.
T1.java (data class):
package demo;
import java.io.Serializable;
// data class (row in database)
public class T1 implements Serializable {
public static final String VER = "Verified";
public static final String NOTVER = "Not verified";
private int f1;
private String f2;
private String f3;
public T1() {
this(0, "", "");
}
public T1(int f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
DB.java (simulated database):
package demo;
import java.util.ArrayList;
import java.util.List;
// simulated database
public class DB {
private static List<T1> db;
static {
db = new ArrayList<T1>();
db.add(new T1(1,"A", T1.VER));
db.add(new T1(2,"BB", T1.VER));
db.add(new T1(3,"CCC", T1.VER));
db.add(new T1(4,"DDDD", T1.VER));
db.add(new T1(5,"EEEEE", T1.NOTVER));
}
public static List<T1> getAll() {
return db;
}
public static void saveOne(T1 o) {
db.add(o);
}
}
Test.java (backing bean):
package demo;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
@ManagedBean
@RequestScoped
public class Test {
// form fields
private Integer f1;
private String f2;
private String f3;
public Integer getF1() {
return f1;
}
public void setF1(Integer f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
// options list
public List<String> getOptions() {
List<String> res = new ArrayList<String>();
res.add("");
res.add(T1.VER);
res.add(T1.NOTVER);
return res;
}
// show data
public List<T1> getData() {
return DB.getAll();
}
// form submit
public void save() {
DB.saveOne(new T1(f1, f2, f3));
}
}
web.xml (configuration of web application):
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- setup JSF -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- use .jsf extension (foobar.jsf will use foobar.jsp or foobar.xhtml as view) -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<!-- instruct JSF to store state server side not client side -->
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<!-- enable dependency injection (necessary Tomcat, not needed JBoss) -->
<resource-env-ref>
<resource-env-ref-name>BeanManager</resource-env-ref-name>
<resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
</resource-env-ref>
<!-- make index.jsf default -->
<welcome-file-list>
<welcome-file>index.jsf</welcome-file>
</welcome-file-list>
</web-app>
faces-config.xml (configuration of JSF):
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
</faces-config>
Note: this configuration file is empty, but the file must be there. And it can be used for advanced configuration.
Context.xml (adds support for CDI in Tomcat):
<Context>
<Resource name="BeanManager"
auth="Container"
type="javax.enterprise.inject.spi.BeanManager"
factory="org.jboss.weld.resources.ManagerObjectFactory" />
</Context>
beans.xml (required for CDI):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="annotated">
</beans>
JSP is the Java standard web page technology.
JSP is covered in detail in Java EE tricks.
index.jsp:
<%@ page language="java" %>
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<html>
<head>
<title>JSF with JSP</title>
</head>
<body>
<f:view>
<h1>JSF with JSP</h1>
<h2>Show data (dataTable):</h2>
<h:dataTable value="#{test.data}" var="o" border="1">
<h:column><f:facet name="header"><h:outputText value="F1"/></f:facet><h:outputText value="#{o.f1}"/></h:column>
<h:column><f:facet name="header"><h:outputText value="F2"/></f:facet><h:outputText value="#{o.f2}"/></h:column>
<h:column><f:facet name="header"><h:outputText value="F3"/></f:facet><h:outputText value="#{o.f3}"/></h:column>
</h:dataTable>
<h2>Show data (forEach):</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<c:forEach items="#{test.data}" var="o">
<tr>
<td><h:outputText value="#{o.f1}"/></td>
<td><h:outputText value="#{o.f2}"/></td>
<td><h:outputText value="#{o.f3}"/></td>
</tr>
</c:forEach>
</table>
<h2>Add data:</h2>
<h:form>
F1: <h:inputText value="#{test.f1}"/>
<br>
F2: <h:inputText value="#{test.f2}"/>
<br>
F3: <h:selectOneMenu value="#{test.f3}"><f:selectItems value="#{test.options}"/></h:selectOneMenu>
<br>
<h:commandButton value="Add" action="#{test.save}"/>
</h:form>
</f:view>
</body>
</html>
Packaging of war file:
0 Thu Dec 01 13:49:40 EST 2022 META-INF/
109 Thu Dec 01 13:49:38 EST 2022 META-INF/MANIFEST.MF
0 Thu Dec 01 13:49:40 EST 2022 WEB-INF/
1375 Mon Dec 27 19:30:16 EST 2021 WEB-INF/web.xml
0 Thu Dec 01 13:49:40 EST 2022 WEB-INF/classes/
0 Thu Dec 01 13:49:40 EST 2022 WEB-INF/classes/demo/
762 Thu Dec 01 13:49:40 EST 2022 WEB-INF/classes/demo/DB.class
746 Thu Dec 01 13:49:40 EST 2022 WEB-INF/classes/demo/T1.class
1289 Thu Dec 01 13:49:40 EST 2022 WEB-INF/classes/demo/Test.class
1420 Wed Nov 23 19:46:08 EST 2022 index.jsp
317 Mon Jul 01 22:09:18 EDT 2019 WEB-INF/beans.xml
300 Mon Dec 27 19:12:44 EST 2021 WEB-INF/faces-config.xml
226 Tue Jul 02 20:02:18 EDT 2019 META-INF/Context.xml
The result looks like:
Facelets are XHTML with special JSF tags.
index.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>JSF with facelet</title>
</h:head>
<h:body>
<f:view>
<h1>JSF with facelet</h1>
<h2>Show data (dataTable):</h2>
<h:dataTable value="#{test.data}" var="o" border="1">
<h:column><f:facet name="header">F1</f:facet>#{o.f1}</h:column>
<h:column><f:facet name="header">F2</f:facet>#{o.f2}</h:column>
<h:column><f:facet name="header">F3</f:facet>#{o.f3}</h:column>
</h:dataTable>
<h2>Show data (repeat):</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<ui:repeat value="#{test.data}" var="o">
<tr>
<td><h:outputText value="#{o.f1}"/></td>
<td><h:outputText value="#{o.f2}"/></td>
<td><h:outputText value="#{o.f3}"/></td>
</tr>
</ui:repeat>
</table>
<h2>Add data:</h2>
<h:form>
F1: <h:inputText value="#{test.f1}"/>
<br/>
F2: <h:inputText value="#{test.f2}"/>
<br/>
F3: <h:selectOneMenu value="#{test.f3}"><f:selectItems value="#{test.options}"/></h:selectOneMenu>
<br/>
<h:commandButton value="Add" action="#{test.save}"/>
</h:form>
</f:view>
</h:body>
</html>
Packaging of war file:
0 Thu Dec 01 13:59:40 EST 2022 META-INF/
109 Thu Dec 01 13:59:38 EST 2022 META-INF/MANIFEST.MF
0 Thu Dec 01 13:59:40 EST 2022 WEB-INF/
1375 Mon Dec 27 19:30:16 EST 2021 WEB-INF/web.xml
0 Thu Dec 01 13:59:40 EST 2022 WEB-INF/classes/
0 Thu Dec 01 13:59:40 EST 2022 WEB-INF/classes/demo/
762 Thu Dec 01 13:59:40 EST 2022 WEB-INF/classes/demo/DB.class
746 Thu Dec 01 13:59:40 EST 2022 WEB-INF/classes/demo/T1.class
1289 Thu Dec 01 13:59:40 EST 2022 WEB-INF/classes/demo/Test.class
1220 Wed Nov 23 19:46:46 EST 2022 index.xhtml
317 Mon Jul 01 22:09:18 EDT 2019 WEB-INF/beans.xml
300 Mon Dec 27 19:12:44 EST 2021 WEB-INF/faces-config.xml
226 Tue Jul 02 20:02:18 EDT 2019 META-INF/Context.xml
The result looks like:
Facelets can be written so they are more like plain XHTML by replacing JSF tags with jsfc attributes on XHTML tags.
In theory that makes it possible for HTML designers to work with the pages offline.
index.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<head>
<title>JSF with inverted facelet</title>
</head>
<body>
<h1>JSF with inverted facelet</h1>
<h2>Show data (dataTable):</h2>
<table jsfc="h:dataTable" value="#{test.data}" var="o" border="1">
<tr>
<th jsfc="h:column"><span jsfc="f:facet" name="header">F1</span>#{o.f1}</th>
<th jsfc="h:column"><span jsfc="f:facet" name="header">F2</span>#{o.f2}</th>
<th jsfc="h:column"><span jsfc="f:facet" name="header">F3</span>#{o.f3}</th>
</tr>
<tr jsfc="ui:remove">
<td>1</td>
<td>A</td>
<td>X</td>
</tr>
<tr jsfc="ui:remove">
<td>2</td>
<td>B</td>
<td>X</td>
</tr>
</table>
<h2>Show data (repeat):</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<tr jsfc="ui:repeat" value="#{test.data}" var="o">
<td><span jsfc="h:outputText" value="#{o.f1}"/></td>
<td><span jsfc="h:outputText" value="#{o.f2}"/></td>
<td><span jsfc="h:outputText" value="#{o.f3}"/></td>
</tr>
<tr jsfc="ui:remove">
<td>1</td>
<td>A</td>
<td>X</td>
</tr>
<tr jsfc="ui:remove">
<td>2</td>
<td>B</td>
<td>X</td>
</tr>
</table>
<h2>Add data:</h2>
<form jsfc="h:form">
F1: <input type="text" jsfc="h:inputText" value="#{test.f1}"/>
<br/>
F2: <input type="text" jsfc="h:inputText" value="#{test.f2}"/>
<br/>
F3: <select jsfc="h:selectOneMenu" value="#{test.f3}"><span jsfc="f:selectItems" value="#{test.options}"></span></select>
<br/>
<h:commandButton value="Add" action="#{test.save}"/>
</form>
</body>
</html>
Packaging of war file:
0 Thu Dec 01 14:03:16 EST 2022 META-INF/
109 Thu Dec 01 14:03:14 EST 2022 META-INF/MANIFEST.MF
0 Thu Dec 01 14:03:16 EST 2022 WEB-INF/
1375 Mon Dec 27 19:30:16 EST 2021 WEB-INF/web.xml
0 Thu Dec 01 14:03:16 EST 2022 WEB-INF/classes/
0 Thu Dec 01 14:03:14 EST 2022 WEB-INF/classes/demo/
762 Thu Dec 01 14:03:14 EST 2022 WEB-INF/classes/demo/DB.class
746 Thu Dec 01 14:03:14 EST 2022 WEB-INF/classes/demo/T1.class
1289 Thu Dec 01 14:03:14 EST 2022 WEB-INF/classes/demo/Test.class
1641 Wed Nov 23 19:49:52 EST 2022 index.xhtml
317 Mon Jul 01 22:09:18 EDT 2019 WEB-INF/beans.xml
300 Mon Dec 27 19:12:44 EST 2021 WEB-INF/faces-config.xml
226 Tue Jul 02 20:02:18 EDT 2019 META-INF/Context.xml
The result looks like:
Tapestry is an old but not very well-known component style web application framework for Java.
| Name and creator | Apache Tapestry / open source |
| History | Version 2.0 in 2002(!) Moved to Apache in 2003 with version 3.0 Version 5.0 in 2008 |
| Programming language | Java |
| View technology | TML |
| Deployment | Servlet container Spring Boot |
| Other technical characteristics | Tapestry automatically use CSS and JavaScript so look and feel is not "plain HTML" |
| Status | Actively maintained, not widely used |
Index.tml (the view):
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd" xmlns:p="tapestry:parameter">
<head>
<title>Tapestry</title>
</head>
<body>
<h1>Tapestry</h1>
<h2>Show data:</h2>
<t:grid source="data">
</t:grid>
<h2>Add data:</h2>
<t:form t:id="addForm">
<t:label for="f1">F1:</t:label><t:textfield t:id="f1"/>
<t:label for="f2">F2:</t:label><t:textfield t:id="f2"/>
<t:label for="f3">F3:</t:label><t:select t:id="f3" model="options"/>
<t:submit value="Add"/>
</t:form>
</body>
</html>
Note how short it is.
Index.java (Java code behind the TML view):
package demo.pages;
import java.util.List;
import java.util.ArrayList;
import org.apache.tapestry5.annotations.*;
import org.apache.tapestry5.corelib.components.Form;
import demo.T1;
import demo.DB;
public class Index {
// form fields
@Persist
@Property
private String f1;
@Persist
@Property
private String f2;
@Persist
@Property
private String f3;
@Component
private Form addForm;
@Property
private List<String> options;
// define form
public Index() {
options = new ArrayList<String>();
options.add(T1.VER);
options.add(T1.NOTVER);
}
// show data
public List<T1> getData() {
return DB.getAll();
}
// form submit
public void onValidateFromAddForm() {
DB.saveOne(new T1(Integer.parseInt(f1), f2, f3));
}
}
TestModule.java:
package demo.services;
public class TestModule {
}
T1.java (data class):
package demo;
import java.io.Serializable;
// data class (row in database)
public class T1 implements Serializable {
public static final String VER = "Verified";
public static final String NOTVER = "Not verified";
private int f1;
private String f2;
private String f3;
public T1() {
this(0, "", "");
}
public T1(int f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
DB.java (simulated database):
package demo;
import java.util.ArrayList;
import java.util.List;
// simulated database
public class DB {
private static List<T1> db;
static {
db = new ArrayList<T1>();
db.add(new T1(1,"A", T1.VER));
db.add(new T1(2,"BB", T1.VER));
db.add(new T1(3,"CCC", T1.VER));
db.add(new T1(4,"DDDD", T1.VER));
db.add(new T1(5,"EEEEE", T1.NOTVER));
}
public static List<T1> getAll() {
return db;
}
public static void saveOne(T1 o) {
db.add(o);
}
}
web.xml (configuring the web application):
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- setup Tapestry -->
<context-param>
<param-name>tapestry.app-package</param-name>
<param-value>demo</param-value>
</context-param>
<filter>
<filter-name>Test</filter-name>
<filter-class>org.apache.tapestry5.TapestryFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Test</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Packaging of war file:
0 Thu Dec 01 19:31:10 EST 2022 META-INF/
109 Thu Dec 01 19:31:08 EST 2022 META-INF/MANIFEST.MF
0 Thu Dec 01 19:31:10 EST 2022 WEB-INF/
705 Wed Dec 29 20:28:40 EST 2021 WEB-INF/web.xml
0 Thu Dec 01 19:31:10 EST 2022 WEB-INF/classes/
0 Thu Dec 01 19:31:10 EST 2022 WEB-INF/classes/demo/
762 Thu Dec 01 19:31:10 EST 2022 WEB-INF/classes/demo/DB.class
746 Thu Dec 01 19:31:10 EST 2022 WEB-INF/classes/demo/T1.class
0 Thu Dec 01 19:31:10 EST 2022 WEB-INF/classes/demo/pages/
1185 Thu Dec 01 19:31:10 EST 2022 WEB-INF/classes/demo/pages/Index.class
0 Thu Dec 01 19:31:10 EST 2022 WEB-INF/classes/demo/services/
139 Thu Dec 01 19:31:10 EST 2022 WEB-INF/classes/demo/services/TestModule.class
0 Thu Dec 01 19:31:10 EST 2022 WEB-INF/lib/
163650 Wed Dec 29 20:23:58 EST 2021 WEB-INF/lib/antlr-runtime-3.3.jar
133776 Wed Dec 29 20:23:32 EST 2021 WEB-INF/lib/beanmodel-5.7.3.jar
116058 Wed Dec 29 20:23:34 EST 2021 WEB-INF/lib/commons-5.7.3.jar
73098 Wed Dec 29 20:23:58 EST 2021 WEB-INF/lib/commons-codec-1.5.jar
556550 Wed Dec 29 20:23:36 EST 2021 WEB-INF/lib/plastic-5.7.3.jar
41139 Wed Jun 19 21:59:36 EDT 2019 WEB-INF/lib/slf4j-api-1.7.26.jar
8476 Wed Jun 19 21:59:36 EDT 2019 WEB-INF/lib/slf4j-jdk14-1.7.26.jar
3003207 Wed Dec 29 20:23:42 EST 2021 WEB-INF/lib/tapestry-core-5.7.3.jar
65642 Wed Dec 29 20:23:48 EST 2021 WEB-INF/lib/tapestry-func-5.7.3.jar
64920 Wed Dec 29 20:23:48 EST 2021 WEB-INF/lib/tapestry-http-5.7.3.jar
437959 Wed Dec 29 20:23:50 EST 2021 WEB-INF/lib/tapestry-ioc-5.7.3.jar
40232 Wed Dec 29 20:23:52 EST 2021 WEB-INF/lib/tapestry-json-5.7.3.jar
28313 Wed Dec 29 20:23:56 EST 2021 WEB-INF/lib/tapestry5-annotations-5.7.3.jar
504 Wed Nov 23 19:58:52 EST 2022 WEB-INF/classes/demo/pages/Index.tml
The result looks like:
App.java (main program):
package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
@SpringBootApplication
public class App extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(AppConfiguration.class);
}
public static void main(String[] args) throws Exception {
SpringApplication application = new SpringApplication(App.class);
application.setApplicationContextClass(AnnotationConfigWebApplicationContext.class);
SpringApplication.run(App.class, args);
}
}
AppConfiguration.java (configuration):
package demo;
import org.apache.tapestry5.TapestryFilter;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import javax.servlet.DispatcherType;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.SessionTrackingMode;
import java.util.EnumSet;
@Configuration
@ComponentScan({ "demo" })
public class AppConfiguration
{
@Bean
public ServletContextInitializer initializer() {
return new ServletContextInitializer() {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter("tapestry.app-package", "demo");
servletContext.setInitParameter("tapestry.development-modules", "demo.services.TestModule");
//servletContext.setInitParameter("tapestry.use-external-spring-context", "true");
servletContext.addFilter("app", TapestryFilter.class).addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR), false, "/*");
//servletContext.addFilter("app", TapestrySpringFilter.class).addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR), false, "/*");
servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE));
}
};
}
@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/error404"));
return factory;
}
}
For Spring Boot deployment just use Maven for directory structure and build the jar file.
Maven generated jar file:
0 Thu Dec 01 19:38:24 EST 2022 META-INF/
492 Thu Dec 01 19:38:24 EST 2022 META-INF/MANIFEST.MF
0 Thu Dec 01 19:38:24 EST 2022 org/
0 Thu Dec 01 19:38:24 EST 2022 org/springframework/
0 Thu Dec 01 19:38:24 EST 2022 org/springframework/boot/
0 Thu Dec 01 19:38:24 EST 2022 org/springframework/boot/loader/
0 Thu Dec 01 19:38:24 EST 2022 org/springframework/boot/loader/data/
2688 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/data/RandomAccessDataFile$DataInputStream.class
0 Thu Dec 01 19:38:24 EST 2022 org/springframework/boot/loader/jar/
5267 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/CentralDirectoryFileHeader.class
3263 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/data/RandomAccessDataFile$FileAccess.class
0 Thu Dec 01 19:38:24 EST 2022 org/springframework/boot/loader/archive/
1487 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/archive/ExplodedArchive$FileEntryIterator$EntryComparator.class
3837 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/archive/ExplodedArchive$FileEntryIterator.class
282 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/data/RandomAccessDataFile$1.class
3116 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/CentralDirectoryEndRecord.class
11548 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/Handler.class
5243 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/archive/ExplodedArchive.class
4015 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/data/RandomAccessDataFile.class
4624 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/CentralDirectoryParser.class
1813 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/ZipInflaterInputStream.class
302 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/archive/Archive$Entry.class
273 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/archive/ExplodedArchive$1.class
485 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/data/RandomAccessData.class
437 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/archive/Archive$EntryFilter.class
7336 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/archive/JarFileArchive.class
1953 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/PropertiesLauncher$PrefixMatchingArchiveFilter.class
1484 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/PropertiesLauncher$ArchiveEntryFilter.class
266 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/PropertiesLauncher$1.class
19737 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/PropertiesLauncher.class
4684 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/Launcher.class
1502 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/MainMethodRunner.class
3608 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/ExecutableArchiveLauncher.class
1721 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/WarLauncher.class
1585 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/JarLauncher.class
0 Thu Dec 01 19:38:24 EST 2022 org/springframework/boot/loader/util/
5203 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/util/SystemPropertyUtils.class
1535 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class
5699 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/LaunchedURLClassLoader.class
616 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/Bytes.class
702 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/JarURLConnection$1.class
1779 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/archive/JarFileArchive$EntryIterator.class
4306 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/JarURLConnection$JarEntryName.class
1081 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/archive/JarFileArchive$JarFileEntry.class
9854 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/JarURLConnection.class
945 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/archive/Archive.class
1233 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/JarFile$2.class
2062 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/JarFile$1.class
1374 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/JarFile$JarFileType.class
15076 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/JarFile.class
4976 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/AsciiBytes.class
1593 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/JarFileEntries$1.class
2046 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/JarFileEntries$EntryIterator.class
540 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/CentralDirectoryVisitor.class
299 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/JarEntryFilter.class
3619 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/JarEntry.class
345 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/FileHeader.class
3650 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/StringSequence.class
14087 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/jar/JarFileEntries.class
1102 Fri Feb 15 10:26:10 EST 2019 org/springframework/boot/loader/archive/ExplodedArchive$FileEntry.class
0 Thu Dec 01 19:38:24 EST 2022 BOOT-INF/
0 Thu Dec 01 19:38:24 EST 2022 BOOT-INF/classes/
0 Wed Nov 23 20:12:12 EST 2022 BOOT-INF/classes/demo/
0 Wed Nov 23 20:12:12 EST 2022 BOOT-INF/classes/demo/components/
0 Wed Nov 23 20:12:12 EST 2022 BOOT-INF/classes/demo/pages/
0 Wed Nov 23 20:12:12 EST 2022 BOOT-INF/classes/demo/services/
0 Thu Dec 01 19:38:18 EST 2022 META-INF/maven/
0 Thu Dec 01 19:38:18 EST 2022 META-INF/maven/demo/
0 Thu Dec 01 19:38:18 EST 2022 META-INF/maven/demo/Test/
27 Thu Dec 01 19:38:14 EST 2022 BOOT-INF/classes/application.yml
283 Wed Nov 23 20:12:12 EST 2022 BOOT-INF/classes/demo/services/TestModule.class
1238 Wed Nov 23 20:12:12 EST 2022 BOOT-INF/classes/demo/T1.class
1560 Wed Nov 23 20:12:12 EST 2022 BOOT-INF/classes/demo/App.class
76 Wed Nov 23 20:12:14 EST 2022 META-INF/maven/demo/Test/pom.properties
1489 Wed Nov 23 20:12:12 EST 2022 BOOT-INF/classes/demo/AppConfiguration.class
2219 Wed Nov 23 20:12:12 EST 2022 BOOT-INF/classes/demo/components/Layout.tml
1009 Wed Nov 23 20:12:12 EST 2022 BOOT-INF/classes/demo/DB.class
8413 Sat Jan 01 17:52:54 EST 2022 META-INF/maven/demo/Test/pom.xml
1952 Wed Nov 23 20:12:12 EST 2022 BOOT-INF/classes/demo/AppConfiguration$1.class
1400 Wed Nov 23 20:12:12 EST 2022 BOOT-INF/classes/demo/pages/Index.class
504 Wed Nov 23 20:12:12 EST 2022 BOOT-INF/classes/demo/pages/Index.tml
2176 Wed Nov 23 20:12:12 EST 2022 BOOT-INF/classes/log4j2.yml
0 Thu Dec 01 19:38:24 EST 2022 BOOT-INF/lib/
398 Fri Feb 15 10:41:22 EST 2019 BOOT-INF/lib/spring-boot-starter-2.1.3.RELEASE.jar
948706 Fri Feb 15 10:08:36 EST 2019 BOOT-INF/lib/spring-boot-2.1.3.RELEASE.jar
1099682 Wed Feb 13 05:32:30 EST 2019 BOOT-INF/lib/spring-context-5.1.5.RELEASE.jar
1257845 Fri Feb 15 10:18:16 EST 2019 BOOT-INF/lib/spring-boot-autoconfigure-2.1.3.RELEASE.jar
26586 Wed Feb 21 15:54:16 EST 2018 BOOT-INF/lib/javax.annotation-api-1.3.2.jar
1293377 Wed Feb 13 05:32:02 EST 2019 BOOT-INF/lib/spring-core-5.1.5.RELEASE.jar
23725 Wed Feb 13 05:31:54 EST 2019 BOOT-INF/lib/spring-jcl-5.1.5.RELEASE.jar
301298 Mon Aug 27 16:23:36 EDT 2018 BOOT-INF/lib/snakeyaml-1.23.jar
406 Fri Feb 15 10:41:44 EST 2019 BOOT-INF/lib/spring-boot-starter-web-2.1.3.RELEASE.jar
405 Fri Feb 15 10:41:44 EST 2019 BOOT-INF/lib/spring-boot-starter-json-2.1.3.RELEASE.jar
33391 Sat Dec 15 23:06:14 EST 2018 BOOT-INF/lib/jackson-datatype-jdk8-2.9.8.jar
100674 Sat Dec 15 23:06:24 EST 2018 BOOT-INF/lib/jackson-datatype-jsr310-2.9.8.jar
8642 Sat Dec 15 23:06:04 EST 2018 BOOT-INF/lib/jackson-module-parameter-names-2.9.8.jar
406 Fri Feb 15 10:41:44 EST 2019 BOOT-INF/lib/spring-boot-starter-tomcat-2.1.3.RELEASE.jar
3287907 Mon Feb 04 16:31:00 EST 2019 BOOT-INF/lib/tomcat-embed-core-9.0.16.jar
250080 Mon Feb 04 16:31:02 EST 2019 BOOT-INF/lib/tomcat-embed-el-9.0.16.jar
265364 Mon Feb 04 16:31:02 EST 2019 BOOT-INF/lib/tomcat-embed-websocket-9.0.16.jar
1155701 Fri Jan 04 14:52:48 EST 2019 BOOT-INF/lib/hibernate-validator-6.0.14.Final.jar
93107 Tue Dec 19 16:23:28 EST 2017 BOOT-INF/lib/validation-api-2.0.1.Final.jar
66469 Wed Feb 14 13:23:28 EST 2018 BOOT-INF/lib/jboss-logging-3.3.2.Final.jar
66540 Tue Mar 27 18:35:34 EDT 2018 BOOT-INF/lib/classmate-1.4.0.jar
1381453 Wed Feb 13 05:32:56 EST 2019 BOOT-INF/lib/spring-web-5.1.5.RELEASE.jar
672558 Wed Feb 13 05:32:08 EST 2019 BOOT-INF/lib/spring-beans-5.1.5.RELEASE.jar
800464 Wed Feb 13 05:33:32 EST 2019 BOOT-INF/lib/spring-webmvc-5.1.5.RELEASE.jar
368947 Wed Feb 13 05:32:22 EST 2019 BOOT-INF/lib/spring-aop-5.1.5.RELEASE.jar
280409 Wed Feb 13 05:32:24 EST 2019 BOOT-INF/lib/spring-expression-5.1.5.RELEASE.jar
408 Fri Feb 15 10:41:54 EST 2019 BOOT-INF/lib/spring-boot-starter-log4j2-2.1.3.RELEASE.jar
1629585 Tue Feb 05 18:12:30 EST 2019 BOOT-INF/lib/log4j-core-2.11.2.jar
23998 Tue Feb 05 18:19:04 EST 2019 BOOT-INF/lib/log4j-jul-2.11.2.jar
4596 Thu Mar 16 17:37:48 EDT 2017 BOOT-INF/lib/jul-to-slf4j-1.7.25.jar
3003207 Mon Aug 09 16:12:42 EDT 2021 BOOT-INF/lib/tapestry-core-5.7.3.jar
437959 Mon Aug 09 16:12:36 EDT 2021 BOOT-INF/lib/tapestry-ioc-5.7.3.jar
65642 Mon Aug 09 16:12:24 EDT 2021 BOOT-INF/lib/tapestry-func-5.7.3.jar
28313 Mon Aug 09 16:12:24 EDT 2021 BOOT-INF/lib/tapestry5-annotations-5.7.3.jar
556550 Mon Aug 09 16:12:22 EDT 2021 BOOT-INF/lib/plastic-5.7.3.jar
2497 Tue Oct 13 16:07:04 EDT 2009 BOOT-INF/lib/javax.inject-1.jar
40232 Mon Aug 09 16:12:38 EDT 2021 BOOT-INF/lib/tapestry-json-5.7.3.jar
133776 Mon Aug 09 16:12:26 EDT 2021 BOOT-INF/lib/beanmodel-5.7.3.jar
116058 Mon Aug 09 16:12:24 EDT 2021 BOOT-INF/lib/commons-5.7.3.jar
167761 Tue Mar 25 07:04:24 EDT 2014 BOOT-INF/lib/antlr-runtime-3.5.2.jar
64920 Mon Aug 09 16:12:38 EDT 2021 BOOT-INF/lib/tapestry-http-5.7.3.jar
25150 Tue Dec 11 12:04:00 EST 2018 BOOT-INF/lib/jakarta.annotation-api-1.3.4.jar
115498 Thu Dec 27 15:30:30 EST 2018 BOOT-INF/lib/jakarta.xml.bind-api-2.3.2.jar
44399 Tue Nov 20 22:13:52 EST 2018 BOOT-INF/lib/jakarta.activation-api-1.2.1.jar
1093432 Wed Sep 12 12:13:52 EDT 2018 BOOT-INF/lib/jaxb-runtime-2.3.1.jar
128076 Wed Sep 12 06:28:46 EDT 2018 BOOT-INF/lib/jaxb-api-2.3.1.jar
70288 Wed Sep 12 12:12:20 EDT 2018 BOOT-INF/lib/txw2-2.3.1.jar
25523 Wed Aug 29 05:23:54 EDT 2018 BOOT-INF/lib/istack-commons-runtime-3.0.7.jar
36073 Tue Apr 24 02:44:02 EDT 2018 BOOT-INF/lib/stax-ex-1.8.jar
311876 Wed Aug 29 07:39:00 EDT 2018 BOOT-INF/lib/FastInfoset-1.2.15.jar
56674 Wed Sep 06 16:13:14 EDT 2017 BOOT-INF/lib/javax.activation-api-1.2.0.jar
2463818 Fri Jan 18 15:24:58 EST 2019 BOOT-INF/lib/jaxws-rt-2.3.2.jar
57877 Thu Dec 27 15:51:06 EST 2018 BOOT-INF/lib/jakarta.xml.ws-api-2.3.2.jar
36161 Thu Dec 27 15:41:42 EST 2018 BOOT-INF/lib/jakarta.xml.soap-api-1.4.1.jar
15860 Thu Dec 27 15:46:16 EST 2018 BOOT-INF/lib/jakarta.jws-api-1.1.1.jar
181165 Fri Dec 28 14:32:46 EST 2018 BOOT-INF/lib/policy-2.7.6.jar
204972 Fri Dec 28 13:31:16 EST 2018 BOOT-INF/lib/gmbal-4.0.0.jar
45451 Mon Dec 17 12:16:18 EST 2018 BOOT-INF/lib/management-api-3.2.1.jar
197485 Fri Dec 28 13:23:26 EST 2018 BOOT-INF/lib/pfl-basic-4.0.1.jar
93886 Fri Dec 28 13:24:32 EST 2018 BOOT-INF/lib/pfl-tf-4.0.1.jar
357914 Fri Dec 28 13:24:10 EST 2018 BOOT-INF/lib/pfl-asm-4.0.1.jar
343539 Fri Dec 28 13:24:20 EST 2018 BOOT-INF/lib/pfl-dynamic-4.0.1.jar
70799 Fri Dec 28 13:24:06 EST 2018 BOOT-INF/lib/pfl-basic-tools-4.0.1.jar
49125 Fri Dec 28 13:24:40 EST 2018 BOOT-INF/lib/pfl-tf-tools-4.0.1.jar
73918 Fri Dec 28 14:33:00 EST 2018 BOOT-INF/lib/streambuffer-1.5.7.jar
67125 Fri Dec 28 12:46:32 EST 2018 BOOT-INF/lib/mimepull-1.9.11.jar
36399 Wed Jan 16 03:51:28 EST 2019 BOOT-INF/lib/ha-api-3.1.12.jar
498818 Tue Jun 12 07:08:22 EDT 2018 BOOT-INF/lib/saaj-impl-1.5.0.jar
513602 Sat Mar 31 01:34:20 EDT 2018 BOOT-INF/lib/woodstox-core-5.1.0.jar
169541 Wed Mar 28 03:40:18 EDT 2018 BOOT-INF/lib/stax2-api-4.1.jar
56615 Wed Sep 12 12:25:44 EDT 2018 BOOT-INF/lib/jaxws-api-2.3.1.jar
46111 Tue Jun 13 16:36:16 EDT 2017 BOOT-INF/lib/javax.xml.soap-api-1.4.0.jar
335042 Tue Oct 17 08:53:20 EDT 2017 BOOT-INF/lib/commons-codec-1.11.jar
23239 Tue Feb 05 18:13:54 EST 2019 BOOT-INF/lib/log4j-slf4j-impl-2.11.2.jar
41203 Thu Mar 16 17:36:32 EDT 2017 BOOT-INF/lib/slf4j-api-1.7.25.jar
266283 Tue Feb 05 18:11:30 EST 2019 BOOT-INF/lib/log4j-api-2.11.2.jar
296324 Thu Nov 09 03:48:28 EST 2017 BOOT-INF/lib/yasson-1.0.1.jar
23665 Mon Jun 19 08:58:02 EDT 2017 BOOT-INF/lib/javax.json.bind-api-1.0.jar
31095 Tue Nov 06 17:05:26 EST 2018 BOOT-INF/lib/javax.json-api-1.1.4.jar
113874 Tue May 09 12:04:46 EDT 2017 BOOT-INF/lib/cdi-api-2.0.jar
73063 Thu Apr 25 15:52:38 EDT 2013 BOOT-INF/lib/javax.el-api-3.0.0.jar
24404 Fri Apr 26 16:10:40 EDT 2013 BOOT-INF/lib/javax.interceptor-api-1.2.jar
101089 Thu Nov 02 18:57:44 EDT 2017 BOOT-INF/lib/javax.json-1.1.2.jar
1349339 Tue Jun 12 01:14:32 EDT 2018 BOOT-INF/lib/jackson-databind-2.9.6.jar
66519 Sat Jul 29 20:53:26 EDT 2017 BOOT-INF/lib/jackson-annotations-2.9.0.jar
325619 Sat Dec 15 13:19:12 EST 2018 BOOT-INF/lib/jackson-core-2.9.8.jar
41291 Tue Jun 12 04:59:46 EDT 2018 BOOT-INF/lib/jackson-dataformat-yaml-2.9.6.jar
85353 Tue Jul 12 13:10:04 EDT 2011 BOOT-INF/lib/javax.servlet-api-3.0.1.jar
The result looks like:
Wicket really makes web applications look like a desktop application.
| Name and creator | Apache Wicket / open source |
| History | Version 1.0 in 2005 Moved to Apache in 2007 with version 1.3 Version 6.0 in 2012 Version 9.0 in 2020 |
| Programming language | Java |
| View technology | XHTML |
| Deployment | Servlet container |
| Other technical characteristics | |
| Status | Actively maintained, small but enthusiastic user base |
TestPage.html:
<html xmlns:wicket="http://wicket.apache.org">
<head>
<title>Wicket</title>
</head>
<body>
<h1>Wicket</h1>
<h2>Show data:</h2>
<table border="1">
<tr wicket:id="data">
<td wicket:id="f1"></td>
<td wicket:id="f2"></td>
<td wicket:id="f3"></td>
</tr>
</table>
<h2>Add data:</h2>
<form wicket:id = "addForm">
F1: <input type="text" name="f1" wicket:id="f1"/>
<br/>
F2: <input type="text" name="f2" wicket:id="f2"/>
<br/>
F3: <select name="f3" wicket:id="f3"/>
<br/>
<input type="submit" value="Add"/>
</form>
</body>
</html>
TestPage.java (code behind TestPage.html):
package demo;
import java.util.List;
import java.util.ArrayList;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.PropertyListView;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.util.value.ValueMap;
public class TestPage extends WebPage {
// setup page
public static class AddForm extends Form<ValueMap> {
// form options list
public List<String> getOptions() {
List<String> res = new ArrayList<String>();
res.add(T1.VER);
res.add(T1.NOTVER);
return res;
}
// define form
public AddForm(String name) {
super(name, new CompoundPropertyModel<ValueMap>(new ValueMap()));
add(new TextField<String>("f1"));
add(new TextField<String>("f2"));
add(new DropDownChoice<String>("f3", getOptions()));
}
// form submit
public void onSubmit() {
ValueMap values = getModelObject();
int f1 = Integer.parseInt((String)values.get("f1"));
String f2 = (String)values.get("f2");
String f3 = (String)values.get("f3");
DB.saveOne(new T1(f1, f2, f3));
}
}
public TestPage() {
// define table
add(new PropertyListView<T1>("data", DB.getAll()) {
@Override
protected void populateItem(ListItem<T1> item) {
item.add(new Label("f1"));
item.add(new Label("f2"));
item.add(new Label("f3"));
}
});
add(new AddForm("addForm"));
}
}
Test.java (configure Wicket):
package demo;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.markup.html.WebPage;
public class Test extends WebApplication
{
// define start page
@Override
public Class<? extends WebPage> getHomePage()
{
return TestPage.class;
}
}
T1.java (data class):
package demo;
import java.io.Serializable;
// data class (row in database)
public class T1 implements Serializable {
public static final String VER = "Verified";
public static final String NOTVER = "Not verified";
private int f1;
private String f2;
private String f3;
public T1() {
this(0, "", "");
}
public T1(int f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
DB.java (simulated database):
package demo;
import java.util.ArrayList;
import java.util.List;
// simulated database
public class DB {
private static List<T1> db;
static {
db = new ArrayList<T1>();
db.add(new T1(1,"A", T1.VER));
db.add(new T1(2,"BB", T1.VER));
db.add(new T1(3,"CCC", T1.VER));
db.add(new T1(4,"DDDD", T1.VER));
db.add(new T1(5,"EEEEE", T1.NOTVER));
}
public static List<T1> getAll() {
return db;
}
public static void saveOne(T1 o) {
db.add(o);
}
}
web.xml (configuring web application):
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- setup Wicket -->
<filter>
<filter-name>Test</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
<param-value>demo.Test</param-value>
</init-param>
<init-param>
<param-name>configuration</param-name>
<param-value>deployment</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Test</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Packaging of war file:
0 Thu Dec 01 20:02:42 EST 2022 META-INF/
109 Thu Dec 01 20:02:40 EST 2022 META-INF/MANIFEST.MF
0 Thu Dec 01 20:02:42 EST 2022 WEB-INF/
871 Wed Dec 29 19:28:08 EST 2021 WEB-INF/web.xml
0 Thu Dec 01 20:02:42 EST 2022 WEB-INF/classes/
0 Thu Dec 01 20:02:42 EST 2022 WEB-INF/classes/demo/
762 Thu Dec 01 20:02:42 EST 2022 WEB-INF/classes/demo/DB.class
746 Thu Dec 01 20:02:42 EST 2022 WEB-INF/classes/demo/T1.class
322 Thu Dec 01 20:02:42 EST 2022 WEB-INF/classes/demo/Test.class
1000 Thu Dec 01 20:02:42 EST 2022 WEB-INF/classes/demo/TestPage$1.class
1619 Thu Dec 01 20:02:42 EST 2022 WEB-INF/classes/demo/TestPage$AddForm.class
612 Thu Dec 01 20:02:42 EST 2022 WEB-INF/classes/demo/TestPage.class
0 Thu Dec 01 20:02:42 EST 2022 WEB-INF/lib/
72446 Wed Dec 29 13:57:42 EST 2021 WEB-INF/lib/commons-fileupload-1.4.jar
327135 Tue Dec 28 20:29:46 EST 2021 WEB-INF/lib/commons-io-2.11.0.jar
41139 Wed Jun 19 21:59:36 EDT 2019 WEB-INF/lib/slf4j-api-1.7.26.jar
8476 Wed Jun 19 21:59:36 EDT 2019 WEB-INF/lib/slf4j-jdk14-1.7.26.jar
2345165 Tue Dec 28 16:41:28 EST 2021 WEB-INF/lib/wicket-core-8.13.0.jar
83670 Tue Dec 28 16:41:32 EST 2021 WEB-INF/lib/wicket-request-8.13.0.jar
382868 Tue Dec 28 16:41:32 EST 2021 WEB-INF/lib/wicket-util-8.13.0.jar
546 Wed Nov 23 19:52:42 EST 2022 WEB-INF/classes/demo/TestPage.html
The result looks like:
| Version | Date | Description |
|---|---|---|
| 1.0 | December 3rd 2022 | Initial version |
| 1.1 | February 19th 2023 | Add VB.NET for Win Forms |
See list of all articles here
Please send comments to Arne Vajhøj