-
Notifications
You must be signed in to change notification settings - Fork 137
Java attributes and methods
This GitHub Wiki page covers only Java attributes and methods, including naming conventions, access modifiers, getters, setters, validation, null safety, DTO and JPQL usage, and HMIS-style examples. It intentionally excludes detailed lessons on classes and objects, constructors, and CDI bean scopes.
An attribute is declared inside a class but outside a method.
private String name;
private Date dob;
private boolean retired;General syntax:
accessModifier dataType attributeName;Example:
private Department department;-
private= access modifier. -
Department= type. -
department= attribute name.
Declaration only:
private List<Patient> patients;Declaration with initialization:
private List<Patient> patients = new ArrayList<>();Initializing collections immediately is often safer because it reduces NullPointerException.
Instance fields receive default values automatically.
| Type | Default |
|---|---|
int, long, double
|
0 or 0.0
|
boolean |
false |
| Object references | null |
char |
Unicode zero value |
Local variables do not receive automatic usable values. They must be assigned before reading.
int count;
System.out.println(count); // Compilation errorEach object has its own value.
private String name;Two patients may have different names.
One value belongs to the class and is shared.
private static int objectCount;Declared inside a method and exists only during that method call.
public double calculateNetTotal() {
double finalAmount = total - discount;
return finalAmount;
}finalAmount is local.
Receives a value when a method is called.
public void setName(String name) {
this.name = name;
}The second name is a parameter.
Java data types are divided into primitive types and reference types.
| Type | Example | Common use |
|---|---|---|
byte |
10 |
Very small integer |
short |
1000 |
Small integer |
int |
25 |
Counts and indexes |
long |
100000L |
IDs and large integers |
float |
10.5f |
Decimal with lower precision |
double |
2500.75 |
Financial or measured values in legacy code |
char |
'A' |
Single character |
boolean |
true |
Status flag |
Reference variables point to objects.
String name;
Date createdAt;
Patient patient;
List<Bill> bills;| Primitive | Wrapper |
|---|---|
int |
Integer |
long |
Long |
double |
Double |
boolean |
Boolean |
char |
Character |
Wrapper types can be null; primitives cannot.
private boolean cancelled; // Always true or false
private Boolean approved; // Can be true, false, or nullHMIS DTO constructor queries should normally use matching wrapper types such as Long, Double, Integer, and Boolean when null safety is required.
Access modifiers decide where a class, method, constructor, or field can be used.
Accessible from any package.
public String getName() {
return name;
}Use public for methods that must be called by XHTML, controllers, services, or other packages.
Accessible only inside the same class.
private String name;Fields are normally private to protect object state.
Accessible:
- Inside the same class.
- Inside the same package.
- Inside subclasses in other packages.
protected double total;It is mainly useful in inheritance.
When no access modifier is written, access is limited to the same package.
String internalCode;This is called default access, package-private access, or no modifier.
| Modifier | Same class | Same package | Subclass elsewhere | Any class |
|---|---|---|---|---|
private |
Yes | No | No | No |
| default | Yes | Yes | No | No |
protected |
Yes | Yes | Yes | No |
public |
Yes | Yes | Yes | Yes |
Use:
-
privatefor entity, controller, service, and DTO fields. -
publicfor required getters, setters, actions, and service methods. -
protectedonly when inheritance genuinely requires it. - Package-private for internal package helpers when appropriate.
Belongs to the class rather than one object.
public static boolean isValidAmount(double amount) {
return amount > 0;
}Prevents reassignment, overriding, or inheritance depending on where it is used.
private static final long serialVersionUID = 1L;Declares incomplete behaviour that subclasses must implement.
public abstract class AbstractReport {
public abstract void generate();
}Allows controlled access by multiple threads. It should be used only when required and understood.
The Java keyword transient excludes a field from standard Java serialization.
private transient String temporaryToken;Do not confuse Java's transient keyword with JPA's @Transient annotation.
Tells the JVM that a field may be changed by different threads. It is uncommon in normal HMIS entity/controller code.
A method is a named block of code that performs an operation.
General form:
accessModifier returnType methodName(parameters) {
// body
}Example:
public double calculateNetTotal(double total, double discount) {
return total - discount;
}| Component | Example |
|---|---|
| Access modifier | public |
| Return type | double |
| Method name | calculateNetTotal |
| Parameters | double total, double discount |
| Method body | { return total - discount; } |
public String getName() {
return name;
}public void setName(String name) {
this.name = name;
}public double calculateBalance() {
return netTotal - paidAmount;
}public boolean isDateRangeValid() {
return fromDate != null
&& toDate != null
&& !fromDate.after(toDate);
}public String navigateToReport() {
return "/reports/lab/investigation_report?faces-redirect=true";
}A factory method creates and returns an object.
public static InvestigationSummary createEmpty() {
return new InvestigationSummary("", 0);
}A parameter is declared in the method definition.
public void setDepartment(Department department)department is a parameter.
An argument is the actual value passed to the method.
report.setDepartment(laboratoryDepartment);laboratoryDepartment is the argument.
public List<Bill> findBills(Date fromDate,
Date toDate,
Department department) {
// query
}Java is always pass-by-value.
For an object, Java passes a copy of the reference value. The method can modify the referenced object's internal state, but replacing the local reference does not replace the caller's reference.
public void updatePatientName(Patient patient) {
patient.getPerson().setName("Updated Name");
}This can modify the same object.
public int getCount() {
return count;
}public Department getDepartment() {
return department;
}public List<PatientInvestigation> getResults() {
return results;
}void means the method does not return a value.
public void clearFilters() {
department = null;
investigation = null;
results = new ArrayList<>();
}A void method can still use return; to exit early.
public void process() {
if (fromDate == null || toDate == null) {
return;
}
}Getters and setters provide controlled access to private fields.
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}Primitive boolean getter:
public boolean isRetired() {
return retired;
}Wrapper Boolean getter may use:
public Boolean getApproved() {
return approved;
}An XHTML expression such as:
#{investigationWiseReport.department}normally maps to:
getDepartment()When a user selects a department, JSF calls:
setDepartment(...)JSF may call getters many times during one request. Heavy database queries should not normally be executed directly in simple getters.
Bad:
public List<Bill> getBills() {
return billFacade.findAll();
}Better:
public void process() {
bills = billFacade.findByJpql(...);
}
public List<Bill> getBills() {
return bills;
}A static member belongs to the class.
private static final long serialVersionUID = 1L;public static boolean isPositive(double value) {
return value > 0;
}Call it with the class name:
AmountValidator.isPositive(100.0);Instance:
patient.getName();Static:
Person.checkAgeSex(dob, sex, title);A static method cannot directly access a non-static field because no particular object is selected.
Can be assigned only once.
final int maximumRows = 100;private static final int DEFAULT_MAX_RESULTS = 100;Constants normally use uppercase snake case.
Cannot be overridden.
public final void audit() {
}Cannot be extended.
public final class ReportConstants {
}A final object reference cannot point to a different object, but the object's contents may still be mutable.
final List<String> names = new ArrayList<>();
names.add("A"); // Allowed
// names = new ArrayList<>(); // Not allowedOverloading means methods have the same name but different parameter lists.
public void search() {
}
public void search(String text) {
}
public void search(Date fromDate, Date toDate) {
}The compiler selects the correct method using parameter number and types.
Changing only the return type is not enough:
// Not allowed:
public int find();
public String find();Overriding means a child class replaces a parent method implementation.
@Override
protected EntityManager getEntityManager() {
return entityManager;
}Rules:
- Same method name.
- Same parameter list.
- Compatible return type.
- Access cannot be made more restrictive.
- Use
@Overrideto let the compiler verify it.
Common overridden methods:
@Override
public String toString() {
return name;
}
@Override
public boolean equals(Object object) {
// equality logic
}
@Override
public int hashCode() {
// hash logic
}Fixed size:
String[] names = new String[3];Ordered collection that can grow.
private List<PatientInvestigation> results = new ArrayList<>();Stores unique elements.
Set<String> codes = new HashSet<>();Stores key-value pairs.
Map<String, Object> parameters = new HashMap<>();
parameters.put("fromDate", fromDate);JPQL commonly uses a parameter map in HMIS.
Generics define the contained type.
List<Bill> bills;This is safer than a raw list:
List bills;With generics, the compiler knows list elements are Bill objects.
results.add(result);
results.remove(result);
results.clear();
int size = results.size();
boolean empty = results.isEmpty();null means an object reference does not point to an object.
Unsafe:
String departmentName = bill.getDepartment().getName();If department is null, this throws NullPointerException.
Safe:
String departmentName = "";
if (bill != null
&& bill.getDepartment() != null
&& bill.getDepartment().getName() != null) {
departmentName = bill.getDepartment().getName();
}public void process() {
if (fromDate == null || toDate == null) {
return;
}
// continue safely
}if (Objects.equals(firstId, secondId)) {
// safe when either value is null
}Optional may be useful in service APIs, but it is not normally used as a JPA entity field.
Guard every nullable relationship level.
if (record.getAdministeredBy() != null
&& record.getAdministeredBy().getPerson() != null) {
name = record.getAdministeredBy().getPerson().getName();
}An exception represents an error or unusual condition.
Must be handled or declared.
public void export() throws IOException {
}Extends RuntimeException.
Examples:
NullPointerExceptionIllegalArgumentExceptionIllegalStateException
try {
workbook.write(outputStream);
} catch (IOException e) {
logger.log(Level.SEVERE, "Excel export failed", e);
}Runs whether an exception occurs or not.
try {
// work
} finally {
// cleanup
}Automatically closes resources.
try (Workbook workbook = new XSSFWorkbook()) {
// create workbook
}Bad:
try {
process();
} catch (Exception e) {
}Better:
try {
process();
} catch (PersistenceException e) {
logger.log(Level.SEVERE, "Report query failed", e);
JsfUtil.addErrorMessage("Unable to generate the report.");
}Do not expose private patient data or database details in user-facing error messages.
Annotations add metadata for Java frameworks and tools.
Marks a persistent JPA entity.
@Entity
public class Person {
}Marks the primary key.
@Id
private Long id;Lets the database generate the ID.
@GeneratedValue(strategy = GenerationType.IDENTITY)Registers a CDI bean name for JSF.
@Named
public class InvestigationWiseReport {
}XHTML:
#{investigationWiseReport.results}Keeps a controller across requests in one user session.
@SessionScopedA session-scoped bean should implement Serializable.
Injects an Enterprise JavaBean.
@EJB
private PatientInvestigationFacade patientInvestigationFacade;Injects a CDI-managed dependency.
@Inject
private SessionController sessionController;Injects an EntityManager.
@PersistenceContext(unitName = "hmisPU")
private EntityManager entityManager;Confirms that a parent method is being overridden.
Warns developers that an API should no longer be used for new code.
Tells JPA not to store the field in the database.
@Transient
private String displayName;Defines how legacy java.util.Date is stored.
@Temporal(TemporalType.TIMESTAMP)
private Date createdAt;A JPA entity represents persistent database data.
Simplified HMIS-style entity:
@Entity
public class PatientNote implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
private Patient patient;
@Lob
private String note;
@ManyToOne
private WebUser creater;
@Temporal(TemporalType.TIMESTAMP)
private Date createdAt;
private boolean retired;
@Transient
private String patientDisplayName;
public PatientNote() {
}
// getters and setters
}Usually stored in the database.
private String note;Stores a link to another entity.
@ManyToOne
private Patient patient;Not stored.
@Transient
private String patientDisplayName;When JPA annotations are placed on fields, JPA uses field access and can read/write fields directly.
Entity fields may be used by:
- Existing database columns.
- JPQL.
- XHTML expressions.
- Reports.
- Serialization.
- External integrations.
- Old production data.
Do not casually rename or remove existing entity attributes.
CareCode HMIS entities contain both persisted data and calculated display data.
Example concept:
@Temporal(TemporalType.TIMESTAMP)
private Date dob;
@Transient
private String ageAsString;
public String getAgeAsString() {
calculateAge();
return ageAsString;
}dob is stored, while the age string is calculated.
JPQL queries can use mapped persistent attributes, not arbitrary calculated getter-only properties.
Wrong concept:
SELECT p.nameWithTitle FROM Person pwhen nameWithTitle is calculated and not persisted.
Better:
SELECT p.title, p.name FROM Person pThen combine them in Java or the DTO.
private transient String token;- Java serialization rule.
@Transient
private String displayText;- JPA persistence rule.
A field may use either or both depending on the requirement.
DTO means Data Transfer Object.
It carries only the data required for a use case.
public class InvestigationCountDTO {
private Long investigationId;
private String investigationName;
private Long patientCount;
public InvestigationCountDTO(Long investigationId,
String investigationName,
Long patientCount) {
this.investigationId = investigationId;
this.investigationName = investigationName;
this.patientCount = patientCount;
}
public boolean hasResults() {
return patientCount != null && patientCount > 0;
}
// getters
}Entity:
private Investigation investigation;DTO navigation pattern:
private Long investigationId;
private String investigationName;The DTO is lighter and avoids loading an entire entity graph.
String jpql =
"SELECT new com.divudi.core.data.dto.InvestigationCountDTO("
+ "i.id, i.name, COUNT(pi.id)) "
+ "FROM PatientInvestigation pi "
+ "JOIN pi.investigation i "
+ "WHERE pi.createdAt BETWEEN :fromDate AND :toDate "
+ "GROUP BY i.id, i.name";The HMIS developer guidelines recommend direct DTO queries instead of loading full entities and converting each entity in a loop.
For existing DTOs:
- Keep current attributes.
- Keep current constructors.
- Add new attributes when required.
- Add overloaded constructors rather than breaking existing queries.
JPQL works with Java entity names and mapped attributes, not table-column syntax in the same way as SQL.
SELECT pi
FROM PatientInvestigation pi
WHERE pi.createdAt BETWEEN :fromDate AND :toDateMap<String, Object> parameters = new HashMap<>();
parameters.put("fromDate", fromDate);
parameters.put("toDate", toDate);SELECT new SomeDTO(
entity.id,
entity.name,
entity.total
)must match:
public SomeDTO(Long id, String name, Double total)If an entity field is double or Double, use Double in the DTO constructor rather than an unrelated numeric type.
Unsafe JPQL relationship traversal can remove rows or cause failures.
Use explicit joins where appropriate:
LEFT JOIN b.patient patient
LEFT JOIN patient.person personFor nullable string values in DTO projections, use a safe default when supported:
COALESCE(person.name, '')Do not use calculated getter properties in JPQL unless they are actually mapped persistent attributes.
These methods come from java.lang.Object.
Returns a readable representation.
@Override
public String toString() {
return name;
}It may be used by logs, dropdowns, converters, and debugging.
Do not include sensitive patient information unnecessarily.
Checks logical equality.
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (!(object instanceof Investigation)) {
return false;
}
Investigation other = (Investigation) object;
return Objects.equals(id, other.id);
}Objects that are equal must return the same hash code.
@Override
public int hashCode() {
return Objects.hashCode(id);
}New unsaved entities may have null IDs. Equality based only on IDs needs careful handling.
Legacy HMIS code commonly uses java.util.Date.
@Temporal(TemporalType.TIMESTAMP)
private Date createdAt;Date only.
@Temporal(TemporalType.DATE)
private Date billDate;Time only.
Date and time.
public boolean isValidDateRange() {
if (fromDate == null || toDate == null) {
return false;
}
return !fromDate.after(toDate);
}Date is mutable. Defensive copying may be used in isolated domain models, though existing project conventions must be respected.
Modern Java offers:
LocalDateLocalTimeLocalDateTimeInstant
Do not replace legacy entity date types without checking JPA mappings, existing queries, converters, and production compatibility.
PascalCase:
InvestigationWiseReport
PatientInvestigationFacade
StockDTOcamelCase:
fromDate
patientCount
calculateAge()
findInvestigations()UPPER_SNAKE_CASE:
DEFAULT_MAX_RESULTSretired
cancelled
approvedGetters:
isRetired()
isCancelled()
getApproved()Use plural names:
results
bills
investigationsGood:
generateReport()
clearFilters()
calculateNetTotal()
findActiveInvestigations()Weak:
doIt()
processData2()
abc()Large legacy systems may contain old misspelled attributes or methods kept for backward compatibility. Do not rename them casually. First search:
- Java references.
- JPQL.
- XHTML.
- database schema.
- reports.
- integrations.
- migration scripts.
Bad:
public String name;Better:
private String name;with getters and setters.
Wrong:
Patient.getName();Correct:
patient.getName();Wrong:
new PatientInvestigationFacade();Correct:
@EJB
private PatientInvestigationFacade facade;@Named
@SessionScoped
public class ReportController implements Serializable {
}Load data in an action method or initialization step instead.
Risky:
private List<Bill> bills;Safer:
private List<Bill> bills = new ArrayList<>();Select persisted fields and calculate display text in Java.
Query parameter count, order, and types must match the constructor.
A projected Double should not be sent to a BigDecimal constructor parameter without explicit conversion.
Guard each relationship or use correct joins.
Add an overloaded constructor instead.
Prefer an empty collection when it accurately represents “no results.”
Static mutable data is shared across users and can cause privacy and concurrency problems.
Logs should not unnecessarily include patient names, identifiers, diagnoses, or report values.
public static void main(String[] args)-
public: JVM can access the method. -
static: JVM calls it without creating an object. -
void: it returns no value. -
main: standard starting method name. -
String[] args: command-line arguments.
A Java EE web application is normally started by the application server, not by a business class's main method.
The following example combines attributes, methods, access modifiers, annotations, DTOs, facades, controllers, and XHTML binding. It is a simplified learning example and not a direct replacement for an existing HMIS file.
package com.divudi.core.entity.lab;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.*;
@Entity
public class LabResultAudit implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private PatientInvestigation patientInvestigation;
@ManyToOne(fetch = FetchType.LAZY)
private WebUser creater;
@Temporal(TemporalType.TIMESTAMP)
private Date createdAt;
@Lob
private String comments;
private boolean retired;
@Transient
private String investigationName;
public LabResultAudit() {
}
public Long getId() {
return id;
}
public PatientInvestigation getPatientInvestigation() {
return patientInvestigation;
}
public void setPatientInvestigation(
PatientInvestigation patientInvestigation) {
this.patientInvestigation = patientInvestigation;
}
public WebUser getCreater() {
return creater;
}
public void setCreater(WebUser creater) {
this.creater = creater;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments == null
? null
: comments.trim();
}
public boolean isRetired() {
return retired;
}
public void setRetired(boolean retired) {
this.retired = retired;
}
public String getInvestigationName() {
if (patientInvestigation == null
|| patientInvestigation.getInvestigation() == null) {
return "";
}
return patientInvestigation.getInvestigation().getName();
}
}- Private attributes.
- Primitive
boolean. - Object references.
- JPA annotations.
- No-argument constructor.
- Getter and setter methods.
- Validation/normalization in a setter.
- Calculated transient getter.
- Null safety.
- Serializable entity.
package com.divudi.core.data.dto;
import java.util.Date;
public class LabResultAuditDTO {
private Long auditId;
private String investigationName;
private Date createdAt;
private String creatorName;
private String comments;
public LabResultAuditDTO(Long auditId,
String investigationName,
Date createdAt,
String creatorName,
String comments) {
this.auditId = auditId;
this.investigationName = investigationName;
this.createdAt = createdAt;
this.creatorName = creatorName;
this.comments = comments;
}
public Long getAuditId() {
return auditId;
}
public String getInvestigationName() {
return investigationName;
}
public Date getCreatedAt() {
return createdAt;
}
public String getCreatorName() {
return creatorName;
}
public String getComments() {
return comments;
}
}- Lightweight attributes.
- Parameterized constructor.
- Read-only style through getters.
- No full entity graph in the DTO.
package com.divudi.core.facade;
import com.divudi.core.entity.lab.LabResultAudit;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Stateless
public class LabResultAuditFacade
extends AbstractFacade<LabResultAudit> {
@PersistenceContext(unitName = "hmisPU")
private EntityManager entityManager;
public LabResultAuditFacade() {
super(LabResultAudit.class);
}
@Override
protected EntityManager getEntityManager() {
return entityManager;
}
}- Inheritance.
- Generic type.
- Constructor calling
super. - Method overriding.
- Dependency injection.
- Stateless EJB.
package com.divudi.bean.lab;
import com.divudi.core.data.dto.LabResultAuditDTO;
import com.divudi.core.facade.LabResultAuditFacade;
import java.io.Serializable;
import java.util.*;
import javax.ejb.EJB;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import javax.persistence.TemporalType;
@Named
@SessionScoped
public class LabResultAuditController
implements Serializable {
private static final long serialVersionUID = 1L;
@EJB
private LabResultAuditFacade facade;
private Date fromDate;
private Date toDate;
private List<LabResultAuditDTO> results =
new ArrayList<>();
public void process() {
results.clear();
if (!isDateRangeValid()) {
return;
}
String jpql =
"SELECT new com.divudi.core.data.dto."
+ "LabResultAuditDTO("
+ "a.id, "
+ "a.patientInvestigation.investigation.name, "
+ "a.createdAt, "
+ "COALESCE(person.name, ''), "
+ "a.comments) "
+ "FROM LabResultAudit a "
+ "LEFT JOIN a.creater creator "
+ "LEFT JOIN creator.webUserPerson person "
+ "WHERE a.retired = false "
+ "AND a.createdAt BETWEEN :fromDate AND :toDate "
+ "ORDER BY a.createdAt DESC";
Map<String, Object> parameters = new HashMap<>();
parameters.put("fromDate", fromDate);
parameters.put("toDate", toDate);
results = (List<LabResultAuditDTO>)
facade.findLightsByJpql(
jpql,
parameters,
TemporalType.TIMESTAMP);
}
private boolean isDateRangeValid() {
return fromDate != null
&& toDate != null
&& !fromDate.after(toDate);
}
public void clear() {
fromDate = null;
toDate = null;
results.clear();
}
public Date getFromDate() {
return fromDate;
}
public void setFromDate(Date fromDate) {
this.fromDate = fromDate;
}
public Date getToDate() {
return toDate;
}
public void setToDate(Date toDate) {
this.toDate = toDate;
}
public List<LabResultAuditDTO> getResults() {
return results;
}
}- CDI bean annotations.
- Session scope and serialization.
- EJB injection.
- Collection initialization.
- Public action methods.
- Private validation method.
- Direct DTO query.
- Parameter map.
- Getter/setter binding.
- Null and date validation.
<h:form id="auditForm">
<p:datePicker value="#{labResultAuditController.fromDate}" />
<p:datePicker value="#{labResultAuditController.toDate}" />
<p:commandButton value="Process"
action="#{labResultAuditController.process}"
update="resultPanel" />
<p:commandButton value="Clear"
action="#{labResultAuditController.clear}"
update="@form" />
<p:outputPanel id="resultPanel">
<p:dataTable value="#{labResultAuditController.results}"
var="row"
emptyMessage="No records found">
<p:column headerText="Investigation">
<h:outputText value="#{row.investigationName}" />
</p:column>
<p:column headerText="Created At">
<h:outputText value="#{row.createdAt}" />
</p:column>
<p:column headerText="Created By">
<h:outputText value="#{row.creatorName}" />
</p:column>
<p:column headerText="Comments">
<h:outputText value="#{row.comments}" />
</p:column>
</p:dataTable>
</p:outputPanel>
</h:form>