Add "Java-Architecture"
@@ -0,0 +1,204 @@
|
|||||||
|
# 🏛️ Java Architecture — Patterns & Conventions
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Both Java projects in `pi_mcps` follow standard Jakarta EE layered architecture patterns, built with NetBeans and deployed on JBoss/WildFly. This page documents the common design patterns, conventions, and technology choices shared across [`wellmann-shop`](wellmann-shop) and [`mss-failsafe`](mss-failsafe).
|
||||||
|
|
||||||
|
## Layered Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ Web Layer (JSF/XHTML Facelets) │
|
||||||
|
│ PrimeFaces components + CSS │
|
||||||
|
└──────────────────┬──────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ Controller Layer │
|
||||||
|
│ @Named CDI beans (@SessionScoped / │
|
||||||
|
│ @RequestScoped) as JSF backing beans │
|
||||||
|
└──────────────────┬──────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ Business/Service Layer │
|
||||||
|
│ @Named @SessionScoped CDI beans │
|
||||||
|
│ Business logic, validation, workflows │
|
||||||
|
└──────────────────┬──────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ Persistence Layer │
|
||||||
|
│ JPA entities + @PersistenceContext │
|
||||||
|
│ EntityManager, TypedQuery, JPQL │
|
||||||
|
└──────────────────┬──────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ Database │
|
||||||
|
│ MySQL (wellmann-shop) / configurable │
|
||||||
|
│ Via persistence.xml data source │
|
||||||
|
└─────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Patterns Used
|
||||||
|
|
||||||
|
### Controller Pattern (JSF Backing Beans)
|
||||||
|
|
||||||
|
CDI `@Named` + `@SessionScoped` or `@RequestScoped` beans act as JSF backing beans:
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Named(value = "itemManager")
|
||||||
|
@SessionScoped
|
||||||
|
public class ItemManager implements Serializable {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Customer activeCustomer;
|
||||||
|
|
||||||
|
@PersistenceContext(unitName = "MySQL-Wellmann")
|
||||||
|
private EntityManager em;
|
||||||
|
|
||||||
|
// JSF-bound methods — called from .xhtml via EL expressions
|
||||||
|
public List<Item> getActiveTickets() { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Key characteristics:
|
||||||
|
- `@Named` registers the bean for EL access: `#{itemManager.activeTickets}`
|
||||||
|
- `@SessionScoped` maintains state across HTTP requests in the user session
|
||||||
|
- `Serializable` required for session passivation
|
||||||
|
- `@Inject` for CDI dependency injection between beans
|
||||||
|
|
||||||
|
### JPA Entity Pattern
|
||||||
|
|
||||||
|
Entities are plain POJOs with JPA annotations:
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Entity
|
||||||
|
@Table(name = "ticket")
|
||||||
|
public class Ticket {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "machine_id")
|
||||||
|
private Machine machine;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "ticket", cascade = CascadeType.ALL)
|
||||||
|
private List<Comment> comments;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Entities in `mssfailsafe.datalayer` are shared as a JAR dependency across WAR modules
|
||||||
|
- `@Transactional` on service methods for transaction demarcation
|
||||||
|
- `TypedQuery` + JPQL for type-safe queries
|
||||||
|
|
||||||
|
### JPA Facade Pattern (wellmann-shop)
|
||||||
|
|
||||||
|
NetBeans-generated Facade classes encapsulate entity access:
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Generated by NetBeans — wraps EntityManager CRUD operations
|
||||||
|
public class PaperFacade {
|
||||||
|
@PersistenceContext(unitName = "MySQL-Wellmann")
|
||||||
|
private EntityManager em;
|
||||||
|
|
||||||
|
public Paper find(Object id) { return em.find(Paper.class, id); }
|
||||||
|
public List<Paper> findAll() { ... }
|
||||||
|
public void create(Paper entity) { em.persist(entity); }
|
||||||
|
public void edit(Paper entity) { em.merge(entity); }
|
||||||
|
public void remove(Paper entity) { em.remove(em.merge(entity)); }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Security Pattern
|
||||||
|
|
||||||
|
**wellmann-shop** uses Jakarta Security with PBKDF2 hashing:
|
||||||
|
```java
|
||||||
|
// Custom PBKDF2 implementation via commons-codec
|
||||||
|
public class MyPasswordHash {
|
||||||
|
public static String hash(String password, String salt) {
|
||||||
|
// PBKDF2WithHmacSHA1 via commons-codec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**mss-failsafe** uses Soteria (reference impl) + OmniFaces:
|
||||||
|
```java
|
||||||
|
// Declarative security via javax.security.enterprise
|
||||||
|
// Soteria 1.0 handles identity stores + credential validation
|
||||||
|
// OmniFaces provides programmatic JSF security utilities
|
||||||
|
```
|
||||||
|
|
||||||
|
Both projects enforce role separation at the WAR level via `WEB-INF/web.xml` security constraints — separate `/manager/` and `/user/` URL patterns with different role requirements.
|
||||||
|
|
||||||
|
### Maven Multi-Module Pattern (mss-failsafe)
|
||||||
|
|
||||||
|
Parent POM defines modules and shared properties:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<!-- mss-failsafe/pom.xml (parent) -->
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<modules>
|
||||||
|
<module>mssfailsafe.datalayer</module> <!-- Build first: entities -->
|
||||||
|
<module>userdata</module> <!-- Build second: security/utils -->
|
||||||
|
<module>mssfailsafeWeblayer</module> <!-- Build third: web layer -->
|
||||||
|
<module>mss</module> <!-- Build last: main app -->
|
||||||
|
</modules>
|
||||||
|
```
|
||||||
|
|
||||||
|
Child modules inherit from parent:
|
||||||
|
```xml
|
||||||
|
<parent>
|
||||||
|
<groupId>plate.software</groupId>
|
||||||
|
<artifactId>mss-failsafe</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build Tools
|
||||||
|
|
||||||
|
| Tool | Version | Usage |
|
||||||
|
|---|---|---|
|
||||||
|
| **Apache Maven** | 3.x | Build, dependency management, multi-module |
|
||||||
|
| **maven-compiler-plugin** | 3.8.0 | Java source/target version configuration |
|
||||||
|
| **maven-war-plugin** | 2.3 | WAR packaging, `failOnMissingWebXml=false` |
|
||||||
|
| **NetBeans** | (various) | Original IDE — `nb-configuration.xml` in each module |
|
||||||
|
| **JUnit** | 4.11 | Unit testing |
|
||||||
|
| **Selenium** | 2.44.0 | UI/integration testing (wellmann-shop) |
|
||||||
|
|
||||||
|
## Deployment Target: WildFly / JBoss
|
||||||
|
|
||||||
|
Both projects deploy to WildFly (formerly JBoss):
|
||||||
|
|
||||||
|
```
|
||||||
|
WEB-INF/
|
||||||
|
├── web.xml ← Standard Jakarta EE web descriptor
|
||||||
|
├── jboss-web.xml ← WildFly context root + virtual host config
|
||||||
|
├── jboss-app.xml ← WildFly application metadata
|
||||||
|
├── faces-config.xml ← JSF navigation + managed bean config (wellmann-shop)
|
||||||
|
└── beans.xml ← CDI activation (empty = all CDI beans discovered)
|
||||||
|
```
|
||||||
|
|
||||||
|
`beans.xml` presence in `WEB-INF/` activates CDI bean discovery for the WAR.
|
||||||
|
|
||||||
|
## Technology Evolution: wellmann-shop → mss-failsafe
|
||||||
|
|
||||||
|
| Aspect | wellmann-shop | mss-failsafe |
|
||||||
|
|---|---|---|
|
||||||
|
| Java version | 8 | 11 |
|
||||||
|
| PrimeFaces | 6.2 | 10.0.0 |
|
||||||
|
| Logging | Log4j 1.2.17 | Log4j2 2.14.1 |
|
||||||
|
| Security | Custom PBKDF2 | Soteria + OmniFaces |
|
||||||
|
| Structure | Single WAR | Multi-module (4 modules) |
|
||||||
|
| Domain model | Inline in WAR | Separate `datalayer` JAR |
|
||||||
|
| PDF support | None | Apache PDFBox 2.0.13 |
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
These projects predate Spring Boot and use classic Java EE patterns. They are reference implementations of enterprise Java architecture demonstrating:
|
||||||
|
- JSF/Facelets templating with PrimeFaces rich components
|
||||||
|
- CDI dependency injection without Spring
|
||||||
|
- JPA/EclipseLink ORM without Spring Data
|
||||||
|
- Jakarta Security without Spring Security
|
||||||
|
- Maven multi-module without Spring Boot parent BOM
|
||||||
|
|
||||||
|
Patrick built both projects entirely without AI assistance as hands-on learning — they represent deep practical expertise in the Jakarta EE ecosystem.
|
||||||
Reference in New Issue
Block a user