Création d'une classe commune aux objets métier

Request description

Bonjour,

Sauriez vous m’indiquer comment créer une classe JAVA sans Internal Object lié, que je pourrais placer dans la hiérarchie des héritages entre les objets de mon module et ObjectDB ?
J’ai besoin d’écrire des méthodes communes à toutes mes classes, mais une classe partagée ne convient pas car il faut qu’elles soient toutes dans mon module.

Merci pour votre aide !
Emmanuelle

Bonjour,

Il est tout à fait possible de créer une classe (virtuelle ou non) qui hérite d’ObjectDB (ou de ScriptedObjectDB) pour déclarer des méthodes (public ou protected), à mettre dans un module commun à tous les autres dans un code partagé.

Ensuite chaque objet hérite directement de cette objet commun.

// common class
public abstract class MyCommonObject extends ObjectDB {
	protected void myCommonMethod1() ...
	protected abstract int myMethod2(Grant g) ...
}

// object class
public class MyObject extends com.simplicite.common.MyCommonModule.MyCommonObject  {
	protected int myMethod2(Grant g) ...
}

Sinon, on peut aussi créer une classe utilitaire, avec un singleton pour accéder à ses méthodes / éviter les new à chaque appel, et éviter les appels de méthode directement static difficilement remplaçables dans le class-loader au moment de clear-cache…

// common class as shared code
public class MyTools {
	static private MyTools tools = null; // singleton in JVM
	static public MyTools getInstance() {
		if (tools==null) tools = new MyTools();
		return tools;
	}
	public void myCommonMethod1() ...
}

// usage
MyTools.getInstance().myCommonMethod1();

Merci beaucoup pour ton retour rapide.
J’ai dû mal identifier mon problème ou mal coder mes classes …

J’ai un objet métier A dans com.simplicite.objects.MonModule
A hérite d’une classe partagée B qui est dans com.simplicite.commons.MonModule
B hérite de com.simplicite.util.ObjectDB

Dans mon code partagé, j’ai besoin de faire ceci

B element = (B) getGrant().getTmpObject(elementName)

pour pouvoir appeler les méthodes de ma classe B sur element.
Mais dans le cas où element est un ScriptedObjectDB, j’ai l’erreur suivante

023-08-21 10:07:22,330|SIMPLICITE|WARN||http://simplicite-dev-7bc664cc78-bwxtn:8080||WARN|system|com.simplicite.webapp.servlets.ui.JSONServlet|service||Event: Service error
    java.lang.ClassCastException: class com.simplicite.util.ScriptedObjectDB cannot be cast to class com.simplicite.commons.RCIB.RciCommonObject (com.simplicite.util.ScriptedObjectDB is in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @456abb66; com.simplicite.commons.RCIB.RciCommonObject is in unnamed module of loader com.simplicite.util.engine.DynamicClassLoader @3dbb176d)

J’ai tenté de faire hériter B de ScriptedObjectDB mais j’ai le même souci.
Je me suis trompée quelque part ?

Oui tu peux utiliser ScriptedObjectDB.

Ton erreur ClassCastException indique plutôt que le nouveau class-loader utilise encore une class dans un vieux class-loader.
Quand on fait un clear-cache complet, il faut que toutes les classes soient rechargeables = typiquement pas de définitions static résiduelles dans l’autre CL.

C’est une des raisons pour laquelle on a abandonné la class GrantHooks “static” au profit de PlatformHooks via un singleton “garbageable”.

Il faut que je retire tout ce qui est static, même les variables ?

Surtout pas de class “static”, la définition n’est pas stockée au même endroit dans la JVM. Sinon il faudra redémarrer tomcat en plus du clear cache en cas de changement de ce code. C’est par construction le fonctionnement d’une JVM, on ne peut rien faire par code pour détruire une classe statique à la volée = chargée une fois pour toute.

Pour les variables, c’est moins gênant via accesseur du singleton static qui peut le recréer par code si null dans le nouveau CL (exemple au début du post).

Même en redémarrant Tomcat j’ai cette erreur donc j’ai sûrement un autre souci :frowning:

Le redémarrage doit vider le cache et donc recharger un autre CL, et certaines classes sont restées dans l’ancien CL si c’est bien toujours un pb de ClassCastException entre 2 CL.

Sans le code de A et B, difficile d’aider.

Voici mon code dans B, la ligne qui pose problème est RciCommonObject element = (RciCommonObject) getGrant().getTmpObject(elementName);.
Je n’ai pas de code appelé dans A.

public void archive()
	{
		setFieldValue("rciFieldIsArchived", true);
		save();
		
		if (isComplexObject())
		{
			
			ObjectDB childObjs = getGrant().getTmpObject("ObjectInternal");
			
			childObjs.setFieldFilter("obo_name", "Rci%");
			
			for (String[] childObjTab : childObjs.search())
			{
								
				ObjectDB childObj = getGrant().getTmpObject(childObjTab[childObjs.getFieldIndex("obo_name")]);
				
				AppLog.info(getClass(), "childObj : ",childObj.getName(), getGrant());
				
				if (!childObj.isHistoric())
				{
					for ( ObjectField keyField : childObj.getFields())	
					{
						String joinedObj = keyField.getJoinedObjectName();
						AppLog.info(getClass(), "keyField 1 : ",keyField.getName() + " " + Boolean.toString(keyField.isFunctId()) + " " + Boolean.toString(keyField.isInternalForeignKey())+ " " + joinedObj, getGrant());
						
						if (keyField.isFunctId() && keyField.isInternalForeignKey() && keyField.getRefFieldName() == null && joinedObj != null && !joinedObj.isEmpty() && joinedObj.equals(this.getName()))
						{
							AppLog.info(getClass(), "keyField 2 : ",keyField.getName(), getGrant());
							String elementName = childObj.getName();
							String elementRefField = keyField.getName();
							**RciCommonObject element = (RciCommonObject) getGrant().getTmpObject(elementName);**
							element.setFieldFilter(elementRefField, this.getRowId());
							
							for (String[] elementTab : element.search())
							{
								element.select(elementTab[0]);
								if (element.isArchivable())
								{
									element.setFieldValue("rciFieldIsArchived", true);
									element.save();
								}
							}
						}
					}
				}
			}
		
		}
	}

Oui c’est bien RciCommonObject qui n’est pas castable / rechargé dans le nouveau CL.
Dans la mesure où il sert à l’héritage de méthodes, je ne comprends pas le besoin de le rendre static = plutôt faites pour des méthodes globales.

Bin il n’est pas static :frowning:

public class RciCommonObject extends com.simplicite.util.ScriptedObjectDB {

Il contient surement un truc louche en dehors du heap sinon on aurait pas d’erreur.
Si c’est autre chose, je ne connais pas la soluce, et il faudra nous donner un exemple reproductible.

Oups :woman_facepalming:
Certains de mes business object n’avaient pas de classe java donc n’héritaient pas de mon CommonObject … désolée pour le dérangement !

Ok pas de soucis, même si je vois pas trop le rapport.
pense à prendre des vacances :sweat_smile:

A retenir : si tu touches à des déclarations static, il faut généralement redémarrer tomcat sinon la JVM peut au mieux raler ou au pire rester sur l’ancien code !

Bin j’imagine que par défaut les business objects héritent de ObjectDB non ?
Du coup tant que je n’ai pas associé une classe Java qui hérite de mon CommonObject, je ne peux pas les caster
Enfin c’est ce que je me suis dit :thinking:

Du coup après avoir créé 30 classes vides juste pour héritage à la volée, je serais pas contre une feature qui permettrait de créer cet héritage par défaut :sweat_smile:

This topic was automatically closed 60 minutes after the last reply. New replies are no longer allowed.