Compare commits
No commits in common. "3cfbf9cf6ea3f967b8150eaa4a183b4c129a84fd" and "6f7ae313ce4c50bda1e0473ae8adf55817b71649" have entirely different histories.
3cfbf9cf6e
...
6f7ae313ce
|
@ -117,11 +117,3 @@ Followup: Excess payloads were being added to the welcome page
|
||||||
that caused HTTP "400" errors fetching resources. A fix has
|
that caused HTTP "400" errors fetching resources. A fix has
|
||||||
been made, although the ultimate solution will probably be more
|
been made, although the ultimate solution will probably be more
|
||||||
JSF-friendly.
|
JSF-friendly.
|
||||||
|
|
||||||
## Minor release 2.0.1
|
|
||||||
|
|
||||||
This release can build an installable RPM for Red Hat-compatible
|
|
||||||
systems, including CentOS and its relatives and Fedora.
|
|
||||||
|
|
||||||
Just run ``mvn install`` and the RPM will be produced under the
|
|
||||||
``/target/rpm`` directory.
|
|
|
@ -1,96 +0,0 @@
|
||||||
# GourmetJ application Architecture.
|
|
||||||
|
|
||||||
This is a Spring Boot self-hosted website built on standard JEE
|
|
||||||
components like JavaServer Faces (JSF) and the Java Persistence
|
|
||||||
Architecture (JPA). It is built and can be tested using Maven.
|
|
||||||
|
|
||||||
The Maven pom.xml file determines the build and what dependencies
|
|
||||||
it has. The core dependencies and their versions are determined
|
|
||||||
in the `dependencyManagement` section of the POM. Actual inclusion
|
|
||||||
of dependencies is done in the `dependencies` section.
|
|
||||||
|
|
||||||
Of the 3 dependencyManagement dependencies, the JoinFaces BOM is
|
|
||||||
the most important. It ensures that the proper version of Spring
|
|
||||||
Boot and its dependencies is brought into the `dependencies` as
|
|
||||||
well as allowing the option to select which JSF extension libraries
|
|
||||||
are to be used. For this project, PrimeFaces is the primary JSF
|
|
||||||
framework.
|
|
||||||
|
|
||||||
## Source Code components
|
|
||||||
|
|
||||||
Source code files come in 4 major types:
|
|
||||||
|
|
||||||
1. Spring/Spring Boot support
|
|
||||||
1. JSF Backing Beans
|
|
||||||
1. Data Persistence
|
|
||||||
1. General Utilities (for example data format converters and parsers)
|
|
||||||
|
|
||||||
### Spring and Spring Boot Support
|
|
||||||
|
|
||||||
The application code root package is `com.mousetech.gourmetj`. The
|
|
||||||
Spring configuration classes are located in this package. There
|
|
||||||
are two of them: `SpringPrimeFacesApplication'java`, which is the
|
|
||||||
main class for the app, and `SpringSecurityConfig.java`, which
|
|
||||||
defines security. Security credentials (userid/password) are taken
|
|
||||||
from an external password file whose location is defined by the
|
|
||||||
`application.yml` properties file. There are no security roles, and
|
|
||||||
all site pages are accessible without logging in except for the
|
|
||||||
ones that can modify the database (create/edit recipe).
|
|
||||||
|
|
||||||
Secondary Spring characteristics come from the `WelcomePageRedirect.java`
|
|
||||||
file which defines the site's welcome page (index.html).
|
|
||||||
|
|
||||||
A small bit of Spring Web in the `springweb.PicureController` class.
|
|
||||||
This Controller resolves the image URLs for recipe images and
|
|
||||||
thumbnails.
|
|
||||||
|
|
||||||
### JSF BackingBeans
|
|
||||||
|
|
||||||
The heart of the webapp is in JavaServer Faces Backing Beans which
|
|
||||||
provide the Models for their corresponding View Template (.xhtml)
|
|
||||||
files. The most important beans are the adminMain bean, which
|
|
||||||
generates the recipe list page and the recipeDetail bean, which
|
|
||||||
back the display and editing of a recipe. The CookieBean is
|
|
||||||
a utility class that allows keeping search information in user-side
|
|
||||||
cookies between user sessions and JSFUtils allows access to
|
|
||||||
HTTP/Servlet soecific resources in a way that isolates them from
|
|
||||||
the general application code. That allows platform independence
|
|
||||||
and easier unit testing.
|
|
||||||
|
|
||||||
### Persistence
|
|
||||||
|
|
||||||
Persistence is done via JPA and has 3 layers:
|
|
||||||
|
|
||||||
1. Service layer. This layer fetches and updates "working sets" of
|
|
||||||
related database entity objects. All service methods are
|
|
||||||
Transactions. Working sets passed in or out of the service layer
|
|
||||||
to the higher (business) layer of the app are detached objects,
|
|
||||||
so the Service layer also ensures detaching and re-attaching
|
|
||||||
(merging) as needed for the lower layer functions.
|
|
||||||
|
|
||||||
1. DAO layer. This layer does find/CRUD functions for a single
|
|
||||||
Entity type or sometimes a parent/child Entity set. I've coded this
|
|
||||||
using explicit logic in times past, but in this app, I've leveraged
|
|
||||||
Spring's Repository feature to let it write the grunt code.
|
|
||||||
|
|
||||||
1. Model layer. This layer contains the actual Entity classes,
|
|
||||||
which are all POJOs and have no executable logic except get/set.
|
|
||||||
|
|
||||||
### Utilities
|
|
||||||
|
|
||||||
Most utility services are in the ``utils`` package, except for
|
|
||||||
JSFUtils, which serves as a liason between JSF server-independent
|
|
||||||
code and server platform-specific services.
|
|
||||||
|
|
||||||
## Future considerations
|
|
||||||
|
|
||||||
There's probably still some lint in the POM and perhaps some dead
|
|
||||||
code from deadend solutions that weren't viable. That's how apps
|
|
||||||
are in the Real World.
|
|
||||||
|
|
||||||
Adding an I18N Bundle would probably be nice.
|
|
||||||
|
|
||||||
A Schema file was recently added to the project and it needs to
|
|
||||||
be checked for functionality. A similar `data.sql` is probably
|
|
||||||
needed to be able to fully set up a database from scratch. My
|
|
||||||
current copy was simply cloned from an existing database.
|
|
76
pom.xml
76
pom.xml
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
<groupId>com.mousetech.gourmet</groupId>
|
<groupId>com.mousetech.gourmet</groupId>
|
||||||
<artifactId>gourmetj</artifactId>
|
<artifactId>gourmetj</artifactId>
|
||||||
<version>2.0.1</version>
|
<version>0.3.0</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>GourmetJ</name>
|
<name>GourmetJ</name>
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>3.2.3</version>
|
<version>3.2.2</version>
|
||||||
<relativePath /> <!-- lookup parent from repository -->
|
<relativePath /> <!-- lookup parent from repository -->
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -177,78 +177,6 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>rpm-maven-plugin</artifactId>
|
|
||||||
<version>2.3.0</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>generate-rpm</id>
|
|
||||||
<goals>
|
|
||||||
<goal>rpm</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<license>GPL (c) 2024, mousetech.com</license>
|
|
||||||
<distribution>Gourmetj</distribution>
|
|
||||||
<group>Application/Collectors</group>
|
|
||||||
<packager>Tom Holloway</packager>
|
|
||||||
<prefix>/usr/local</prefix>
|
|
||||||
<changelogFile>src/changelog</changelogFile>
|
|
||||||
<defineStatements>
|
|
||||||
<defineStatement>_unpackaged_files_terminate_build 0</defineStatement>
|
|
||||||
</defineStatements>
|
|
||||||
<mappings>
|
|
||||||
<mapping>
|
|
||||||
<directory>/opt/mousetech/gourmetj</directory>
|
|
||||||
<filemode>750</filemode>
|
|
||||||
<username>gourmetj</username>
|
|
||||||
<groupname>gourmetj</groupname>
|
|
||||||
<sources>
|
|
||||||
<source>
|
|
||||||
<location>
|
|
||||||
target/${project.build.finalName}.jar</location>
|
|
||||||
</source>
|
|
||||||
<softlinkSource>
|
|
||||||
<destination>gourmetj.jar</destination>
|
|
||||||
<location>
|
|
||||||
${project.build.finalName}.jar</location>
|
|
||||||
</softlinkSource>
|
|
||||||
</sources>
|
|
||||||
</mapping>
|
|
||||||
<mapping>
|
|
||||||
<directory>/opt/mousetech/gourmetj</directory>
|
|
||||||
<configuration>true</configuration>
|
|
||||||
<filemode>440</filemode>
|
|
||||||
<username>gourmetj</username>
|
|
||||||
<groupname>gourmetj</groupname>
|
|
||||||
<sources>
|
|
||||||
<source>
|
|
||||||
<location>src/main/conf</location>
|
|
||||||
</source>
|
|
||||||
</sources>
|
|
||||||
</mapping>
|
|
||||||
<mapping>
|
|
||||||
<directory>/etc/systemd/system/</directory>
|
|
||||||
<directoryIncluded>false</directoryIncluded>
|
|
||||||
<configuration>true</configuration>
|
|
||||||
<filemode>440</filemode>
|
|
||||||
<sources>
|
|
||||||
<source>
|
|
||||||
<location>src/main/systemd/gourmetj.service</location>
|
|
||||||
</source>
|
|
||||||
</sources>
|
|
||||||
</mapping>
|
|
||||||
</mappings>
|
|
||||||
<preinstallScriptlet>
|
|
||||||
<script>echo "installing ${project.name} now"
|
|
||||||
/usr/bin/getent passwd gourmetj || /usr/sbin/useradd -r -d /opt/mousetech/gourmetj -s /sbin/nologin gourmetj
|
|
||||||
</script>
|
|
||||||
</preinstallScriptlet>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
# Application user password file
|
|
|
@ -1,29 +0,0 @@
|
||||||
|
|
||||||
# THIS is the application properties used when testing in the IDE
|
|
||||||
# or running stand-alone from the command line.
|
|
||||||
# It augments/overrides application.yml in the JAR
|
|
||||||
joinfaces.jsf.webapp-resources-directory=/resources
|
|
||||||
server.servlet.session.timeout=30m
|
|
||||||
|
|
||||||
spring.thymeleaf.enabled=false
|
|
||||||
server.error.whitelabel.enabled=false
|
|
||||||
|
|
||||||
spring.datasource.url=jdbc:mysql://dbase/recipes
|
|
||||||
#jdbc:sqlite:${home}/recipes.db
|
|
||||||
spring.datasource.username=recipes
|
|
||||||
pring.datasource.password=yumyumyum
|
|
||||||
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
|
|
||||||
|
|
||||||
#Runtime lies and says no longer required, but it defaults to MySQL5.5.0!:
|
|
||||||
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
|
|
||||||
#org.sqlite.hibernate.dialect.SQLiteDialect
|
|
||||||
#spring.jpa.show-sql: true
|
|
||||||
|
|
||||||
# My special properties
|
|
||||||
gourmet.password.file=.gourmetpw
|
|
||||||
|
|
||||||
# This will override aplication.yml
|
|
||||||
#server.servlet.context-parameters.primefaces.THEME=le-frog
|
|
||||||
|
|
||||||
### HttpSession timeout (note effects on detailEdit idleMonitors)
|
|
||||||
server.servlet.session.timeout=35m
|
|
|
@ -3,8 +3,6 @@ package com.mousetech.gourmetj;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.faces.model.SelectItem;
|
import jakarta.faces.model.SelectItem;
|
||||||
import jakarta.inject.Named;
|
import jakarta.inject.Named;
|
||||||
|
@ -49,12 +47,5 @@ public class AppBean {
|
||||||
new SelectItem(RecipeSearchType.rst_BY_INGREDIENT.ordinal(),
|
new SelectItem(RecipeSearchType.rst_BY_INGREDIENT.ordinal(),
|
||||||
"Ingredient"));
|
"Ingredient"));
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Value("${appVersion}")
|
|
||||||
String appVersion = "Not Supplied.";
|
|
||||||
|
|
||||||
public String getAppVersion() {
|
|
||||||
return appVersion;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
</h:head>
|
</h:head>
|
||||||
<h:body>
|
<h:body>
|
||||||
<h1>
|
<h1>
|
||||||
<ui:insert name="title">Gourmet Recipe Manager (web version #{appBean.appVersion})</ui:insert>
|
<ui:insert name="title">Gourmet Recipe Manager (web version)</ui:insert>
|
||||||
</h1>
|
</h1>
|
||||||
<p:ajaxStatus onerror="PF('opError').show()"/>
|
<p:ajaxStatus onerror="PF('opError').show()"/>
|
||||||
<ui:insert name="content">
|
<ui:insert name="content">
|
||||||
|
@ -28,11 +28,10 @@
|
||||||
</ui:insert>
|
</ui:insert>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<h:outputText value="Version #{appBean.appVersion}"/><br/>
|
|
||||||
(C) 2021, 2024 Tim Holloway, Licensed under
|
(C) 2021, 2024 Tim Holloway, Licensed under
|
||||||
the Common Development and Distribution License (CDDL).
|
the Common Development and Distribution License (CDDL).
|
||||||
<p>Based on Gourmet Recipe Manager by T.
|
<p>Based on Gourmet Recipe Manager by T.
|
||||||
Hinkle.</p>
|
Hinkle</p>
|
||||||
</div>
|
</div>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
</h:body>
|
</h:body>
|
||||||
|
|
|
@ -21,9 +21,6 @@ spring:
|
||||||
ddl-auto: none
|
ddl-auto: none
|
||||||
database-platform: org.hibernate.dialect.MySQLDialect
|
database-platform: org.hibernate.dialect.MySQLDialect
|
||||||
|
|
||||||
# From Maven POM:
|
|
||||||
appVersion: "@project.version@"
|
|
||||||
|
|
||||||
# Tracking-modes prevent URL rewrite jsessionid on Primecases
|
# Tracking-modes prevent URL rewrite jsessionid on Primecases
|
||||||
# resources. Which causes "400" errors on initial main.jsf fetch.
|
# resources. Which causes "400" errors on initial main.jsf fetch.
|
||||||
server:
|
server:
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=Gourmet Recipe Manager
|
|
||||||
Documentation=https://gogs.mousetech.com/gourmetj
|
|
||||||
Requires=network-online.target
|
|
||||||
After=network-online.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=gourmetj
|
|
||||||
WorkingDirectory=/opt/mousetech/gourmetj
|
|
||||||
ExecStart=/usr/bin/java -jar gourmetj.jar
|
|
||||||
#Restart=yes
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
Alias=gourmetj.service
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user