SpringBoot (8) Defining the Base.java interface
0. Introduction
Base interface is the interface that has either default methods and has the interface of the methods to be implemented in any class Implementing this interface.
In addition of forcing to define fields as id and description (by means of its getters and setters), there are some methods that are used with Spring Boot applications.
1. Methods
1.1. Getting initial values:
- void getInitializedBase(Map<String, Object> mpObjects)(interface): Assigns the attributes of the class the values of the map "mpObjects" in a NEW instance
- void addDefaultFormValors(Map<String, Object> mpObjects))(interface): Add additional info that may be used in the form, for instance new empty children
1.2. Validation:
- public default int validate(Locale locale) {return 0;} for validating a bean. It should be overridden by the specific bean. Sometimes if the bean is included in another bean's collection, the bigger bean can validate data form choldren and there is no need to override a validation procedure for each of the children classes. The detected errors are stored in a List<String>
- public default void setNumErrors(int numErrors) {}: To get info about errors
- public List<String> getMyErrors(): To get info about errors
1.3. For copying (creating a new instance using the attributes of another instance):
- public default Base CloneWithNoChildIds() { Gets a new instance copying all the fields except the ids of the elements in collections. Similar to a deep copy but does not copy the child's ids.
1.4. Defining the thymeleaf page to use in a CRUD and after save forms:
- public default String getCRUDFormName( ) { return "General_page";}: The name of the thymeleaf page to use as a form. By default the CRUD form is "General_page.html", but it can be changed. This default page has the buttons for changing languages, save and cancel.
- public default String getProcessClassAfterSave() { return "";} The class to be executed after saving the entity. For instance, if you want to get a ticket of the operation.
- public default String getTitleAfterSave() { return "after.title";} Returns the title of the form after satisfactory saving the bean.
- public default String getSubtitleAfterSave() { return "after.subtitle";}: Subtitle of the form after saving
- public default String getPageAfterSave() { return "aftersave_page";} The thymeleaf page to visit.
- List<FieldEdu> getProcessParamsAfterSave(): The params to pass to the after save page
1.5. Sharing info with javascript in the form:
- public default Object getSharedInfo(): Defines the info that javascript can access that may not be contained in the form fields
For using this information this <script> tag should be appended in the html file (thymeleaf)
<!-- @see https://stackoverflow.com/a/63774829/7704658 for sharing info with thymeleaf-->
<script th:inline="javascript">
var sharedInfo = [[${sharedInfo}]];
console.log("sharedInfo="+JSON.stringify(sharedInfo));
</script>
<!-- @see https://stackoverflow.com/a/63774829/7704658 for sharing info with thymeleaf--> <script th:inline="javascript"> var sharedInfo = [[${sharedInfo}]]; console.log("sharedInfo="+JSON.stringify(sharedInfo)); </script>
2. Base.java interface
Here is the code
==========================================================================
package ximo.xotherapps.model.base;
import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.time.LocalDateTime; import java.util.Comparator; import java.util.List; import java.util.ArrayList; import java.util.Locale; import java.util.Map; import java.util.HashMap; import jakarta.persistence.MappedSuperclass; import org.apache.commons.lang3.reflect.FieldUtils; import ximo.config.menus.FieldEdu; /** * <desc>interface that stores the unique information for all classes dao</desc> * <responsibility>Represents a unique object</responsibility> * <coperation>All classes dao</coperation> * @version 0.1 * Create 18-03-2009 * Author Alfred Oliver */ @MappedSuperclass public interface Base extends Comparable<Base>, Serializable{ /** * <desc> Accessor reading which gives us the identifier</desc> * <pre> x is an instance of Base</pre> * <post> the return is the identifier of x </post> * @return Identifier of object */ //public Number getId(); public Long getId(); //public Object getId(); //public void setId(Number pId); public void setId(Long pId); //public void setId(Object pId); /** * <desc> Accessor reading which gives us the description</desc> * <pre> x is an instance of Base</pre> * <post> the return is the description of x </post> * @return Description of object */ public String getDescription(); public void setDescription(String pDescription); /** * <desc> Accessor reading that means that the system should make a log on any JPA operation of this class</desc> * <pre> x is an instance of Base</pre> * <post> the return is the debugLog of x </post> * @return Debug log mode of object */ public default boolean iisDebugLog() {return true;} //public boolean isDebugLog(); // Now isDetailLog is changed by @Audited of Hibernate Envers //public default boolean isDetailLog() {return false;} // If only works with records whose field lastUser is the user (gexflow-DocPendFirma) public default boolean iisFilteredByUser() {return false;} //public boolean isFilteredByUser(); @Override public default int compareTo(Base o) { return getDescription().compareTo(o.getDescription()); } public static Comparator<Base> compareById () { return new Comparator<Base>() { @Override public int compare(Base o1, Base o2) { return o1.getId().compareTo(o2.getId()); } }; } /** * To achieve Audit methods * @return */ public default String getLastUser() { return null;}; public default void setLastUser(String lastUser) {}; public default LocalDateTime getAuditData() { return null;}; public default void setAuditData(LocalDateTime data) {}; public default void setChanges(String user) {}; public default String getCharAction() {return null;}; public default void setCharAction(String charAction) {}; /** To display text in combos **/ public default String ggetComboText() { return getDescription()+"-("+ getId()+")"; }; /**********ONLY FOR DATABASES NOT CREATED BY US (ORVE, SICRES)*********************/ /** Only for fields that have no description field **/ public default String ggetDescriptionField() { return "description"; //return deAnexo.nombreFicheroAnexado; //Ejemplo con una subclase }; /** For using quotes in queries (numbres do not use quotes but strings need quotes **/ public default boolean iisDescriptionANumber() { return false; }; public default Base idToNull() { this.setId(null); return this; }; /** For copying or migrating entities from one DB to another **/ public default boolean iisMakingIdNullBeforePersist() { return true; }; /** For copying or migrating entities from one DB to another **/ /* @PrePersist private void prePersistFunction(){ System.out.println("@PrePersist......"); if (isMakingIdNullBeforePersist()) this.setId(null); } */ //======================================================================== // 01. SPRING BOOT GENERAL FIELDS //======================================================================== public default void setIdioma(int idioma) {} //For storing errors in bean public List<String>getMyErrors(); public default void setNumErrors(int numErrors) {} public default int getNumErrors() {return 0;} public default int getEstat() {return 0;} //0=Actiu, 1=inactiu, 2=eliminat //======================================================================== // 02. FORM AND AFTER SAVE //======================================================================== //The name of the CRUD FORM for the class public default String getCRUDFormName( ) { return "General_page";} //The name of the class to be executed after saving a CRUD that is satisfactory public default String getProcessClassAfterSave() { return "";} //The name of the title in the thymeleaf page used after saving a CRUD that is satisfactory public default String getTitleAfterSave() { return "after.title";} //The name of the subtitle in the thymeleaf page used after saving a CRUD that is satisfactory public default String getSubtitleAfterSave() { return "after.subtitle";} //The name of the thymeleaf page used after saving a CRUD that is satisfactory public default String getPageAfterSave() { return "aftersave_page";} //Parameters to pass to the class to be executed after Save in a CRUD public default List<FieldEdu> getProcessParamsAfterSave() { List<FieldEdu>lFldEdu=new ArrayList<FieldEdu>(); FieldEdu fldEdu=new FieldEdu(); fldEdu.setName("id"); fldEdu.setLabel(""); fldEdu.setType("long"); fldEdu.setValue(""+getId()); //NO QUITAR ???? fldEdu.setComponent("HIDDEN"); //fldEdu.setComponent("NUMBER"); lFldEdu.add(fldEdu); return lFldEdu; } //======================================================================== // 03. VALIDATION, AJAX BUTTON AND SHARED INFO //======================================================================== //Validation method public default int validate(Locale locale) {return 0;} //Method to execute in an Ajax call with an own button of the class public default Map<String,String> ajaxButton(String buttonValue) {return new HashMap<String,String>();} /** * Shared info to be used in javascript * @return */ public default Object getSharedInfo() { return "";} //======================================================================== // 04. INITIALIZATION AND CLONING //======================================================================== /** * For initilizing a new object in CRUD Spring boot * @param locale * @param anyObject * @param stringParams * @return */ public default void getInitializedBase( Map<String,Object> mpObjects) {} /** * For adding any element from a collection or modifying a bean in a CRUD Spring boot * @param anyObject */ public default void addDefaultFormValors(Map<String, Object> mpObjects) {} //Similar to a deep copy but does not copy the child ids public default Base CloneWithNoChildIds() { //Base deepCopy = (Base) SerializationUtils.clone(this); Base aCopy=null; try { aCopy = this.getClass().getConstructor().newInstance(); for(Field fld: FieldUtils.getAllFieldsList(this.getClass())){ //Do not update "id" if (!fld.getName().equalsIgnoreCase("id") && !Modifier.isStatic(fld.getModifiers() )) { if (List.class.isAssignableFrom(fld.getType())) { List<Object> fldCol =(List<Object>)FieldUtils.readField(fld, this , true) ; List<Object> fldColCop =new ArrayList<Object>(); for (int i=0; i<fldCol.size(); i++) { Object obj =fldCol.get(i); if (Base.class.isAssignableFrom(obj.getClass()) ) { fldColCop.add(((Base)obj).CloneWithNoChildIds()); } else { fldColCop.add(obj); } } FieldUtils.writeField(aCopy, fld.getName(), fldColCop, true); } else { try{ FieldUtils.writeField(aCopy, fld.getName(), FieldUtils.readField(this, fld.getName(), true), true); }catch (Exception e) { e.printStackTrace(); } } } } } catch (Exception e) { e.printStackTrace(); } return aCopy; } }
Comentarios
Publicar un comentario