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