[opencms-dev] How to package java classes in an opencms module
Michael Emmerich
m.emmerich at alkacon.com
Tue Aug 12 14:56:34 CEST 2025
Hello Laurent,
the <resources> node in the manifest file tells the system which files
or folders should be exported when the module is exported in OpenCms
All exported resources of a module can be found as individual <file>
sub-nodes in the <files> node. In those nodes, all resource metadata,
like type, date and user created, path, permissions, properties are stored.
Only those resources that are listed in those <file> nodes are imported
when you import a module using this manifest file.
The easiest to do would be:
- Create a new module inside of OpenCms. During Module creation you can
select which folders inside the /system/modules/[your-module-name]/
should be created. By default, your module folder is part of the module
(and everything inside of it).
- Then upload your .jar and .class files in the corresponding /lib and
/classes folder of your module. Make sure that you have set the export
points for the /lib and /classes folder in the module configuration
- Export the module from OpenCms and download it. Not extract it and
take a look at he manifest file to see what is in there.
The format of those <file> nodes is the same that is used in the
manifest files of a database export in OpenCms.
Kind regards,
Michael
Am 08.08.25 um 15:27 schrieb laurent.druart via opencms-dev:
> Hello Michael,
>
> Thank you for your answer.
>
> The goal of java classes in a module is automatic creation of my
> context on OpenCMS startup, that’s why I implemented
>
> LibraryInitializerextends A_CmsModuleActionimplements I_CmsEventListener
>
> In a previous test I had a section « resources » like this
>
> <resources>
> <resource uri="/system/modules/com.opencms.library/"/>
> </resources>
>
> but not working at all.
>
> So I’ve to create a file section per class in my module? Documentation
> is not clear on manifest.xml. Do you have an exemple with java classes
> and lib dependencies?
>
> Thanks a lot.
>
> Kind regards,
>
> Laurent
>
>> Le 8 août 2025 à 14:30, Michael Emmerich via opencms-dev
>> <opencms-dev at opencms.org> a écrit :
>>
>> Laurent,
>>
>> from you manifest, I see that you have not assigned any resources to
>> your module. So no resources are imported when you import the module,
>> therefore the .jar and .classes are missing. I see that you have
>> defined the export points, but without the imported file, this will
>> not work.
>>
>> However, we usually do not put .jar or .class files in our modules,
>> we deploy them separately on the server as yo have to restart it
>> anyway after deploying some .jar and .class files.
>>
>>
>> Kind regards,
>>
>> Michael
>>
>>
>>
>> Am 08.08.25 um 11:22 schrieb laurent.druart via opencms-dev:
>>> Hello,
>>>
>>> In add-on to my previous e-mail, here is the content/structure of my
>>> zip files :
>>>
>>>
>>> And the content of my manifest.xml :
>>>
>>> <?xml version="1.0" encoding="UTF-8"?>
>>> <export>
>>> <info>
>>> <creator>OpenCMS Module Builder</creator>
>>> <opencms_version>19.0</opencms_version>
>>> <createdate>Wed, 07 Aug 2025 10:00:00 GMT</createdate>
>>> <project>Offline</project>
>>> <export_version>7</export_version>
>>> </info>
>>>
>>> <module>
>>> <name>com.opencms.library</name>
>>> <nicename>OpenCMS Spring Data JDBC Library</nicename>
>>> <group>Custom Libraries</group>
>>> <class>com.opencms.library.integration.LibraryInitializer</class>
>>> <description>Librairie Spring classique pour OpenCMS avec
>>> accès aux données PostgreSQL</description>
>>> <version>1.0.0</version>
>>> <authorname>Laurent Druart</authorname>
>>> <authoremail>laurent.druart at ldict.be</authoremail>
>>> <datecreated>Wed, 07 Aug 2025 10:00:00 GMT</datecreated>
>>> <userinstalled>Admin</userinstalled>
>>> <dateinstalled>Wed, 07 Aug 2025 10:00:00 GMT</dateinstalled>
>>>
>>> <dependencies/>
>>>
>>> <exportpoints>
>>> <exportpoint
>>> uri="/system/modules/com.opencms.library/classes/"
>>> destination="WEB-INF/classes/"/>
>>> <exportpoint
>>> uri="/system/modules/com.opencms.library/lib/"
>>> destination="WEB-INF/lib/"/>
>>> </exportpoints>
>>> <resources/>
>>> <parameters>
>>> <param name="spring.auto.init">true</param>
>>> </parameters>
>>> </module>
>>>
>>> <files/>
>>> </export>
>>>
>>> I tried to import the zip in the modules app, module is created but
>>> classes and lib are not copied in WEB-INF folders and in the
>>> explorer app there are no « com.opencms.library » entries in
>>> /system/modules
>>>
>>> Thanks for your help.
>>>
>>> Regards,
>>>
>>> Laurent
>>>
>>>> Le 7 août 2025 à 16:41, laurent.druart via opencms-dev
>>>> <opencms-dev at opencms.org> a écrit :
>>>>
>>>> Hello,
>>>>
>>>> I’m still testing OpenCMS and i wrote a very small library, a
>>>> spring based library. I want to use the beans in my jsp so i wrote
>>>> 2 classes:
>>>>
>>>> SpringBeanUtils :
>>>>
>>>> public class SpringBeanUtils {
>>>>
>>>> private static final Log LOG = CmsLog.getLog(SpringBeanUtils.class);
>>>>
>>>> /**
>>>> * Récupère le service utilisateur
>>>> * Exemple d'utilisation dans une page JSP :
>>>> * <%
>>>> * UserService userService = SpringBeanUtils.getUserService();
>>>> * List<User> users = userService.getAllActiveUsers();
>>>> * %>
>>>> */
>>>> public static UserService getUserService() {
>>>> try {
>>>> return LibraryInitializer.getBean(UserService.class);
>>>> } catch (Exception e) {
>>>> LOG.error("Erreur lors de la récupération du
>>>> UserService", e);
>>>> throw new RuntimeException("Service utilisateur non
>>>> disponible", e);
>>>> }
>>>> }
>>>>
>>>> /**
>>>> * Méthode générique pour récupérer n'importe quel service
>>>> * Exemple :
>>>> * MyService service = SpringBeanUtils.getService(MyService.class);
>>>> */
>>>> public static <T> T getService(Class<T> serviceClass) {
>>>> try {
>>>> return LibraryInitializer.getBean(serviceClass);
>>>> } catch (Exception e) {
>>>> LOG.error("Erreur lors de la récupération du service: "
>>>> + serviceClass.getSimpleName(), e);
>>>> throw new RuntimeException("Service non disponible: " +
>>>> serviceClass.getSimpleName(), e);
>>>> }
>>>> }
>>>>
>>>> /**
>>>> * Récupère un bean par son nom
>>>> * Exemple :
>>>> * Object bean = SpringBeanUtils.getBean("userService");
>>>> */
>>>> public static Object getBean(String beanName) {
>>>> try {
>>>> return LibraryInitializer.getBean(beanName);
>>>> } catch (Exception e) {
>>>> LOG.error("Erreur lors de la récupération du bean: " +
>>>> beanName, e);
>>>> throw new RuntimeException("Bean non disponible: " +
>>>> beanName, e);
>>>> }
>>>> }
>>>>
>>>> /**
>>>> * Vérifie si le contexte Spring est disponible
>>>> */
>>>> public static boolean isAvailable() {
>>>> return LibraryInitializer.isSpringContextAvailable();
>>>> }
>>>>
>>>> /**
>>>> * Méthode utilitaire pour vérifier la disponibilité avant
>>>> utilisation
>>>> */
>>>> public static void ensureAvailable() {
>>>> if (!isAvailable()) {
>>>> throw new IllegalStateException(
>>>> "Le contexte Spring n'est pas disponible. " +
>>>> "Vérifiez que le module est correctement
>>>> initialisé."
>>>> );
>>>> }
>>>> }
>>>> }
>>>>
>>>> with static method getUserService() I can call the userService
>>>> bean. No problem with it.
>>>>
>>>> And second class LibraryInitializer wich must initialise the spring
>>>> context and configure it:
>>>>
>>>> public class LibraryInitializer extends A_CmsModuleAction
>>>> implements I_CmsEventListener {
>>>>
>>>> private static final String MODULE_NAME = "opencms-spring-library";
>>>> private static ApplicationContext springContext;
>>>> private static final org.apache.commons.logging.Log LOG =
>>>> CmsLog.getLog(LibraryInitializer.class);
>>>>
>>>> /**
>>>> * Initialisation du module
>>>> */
>>>> @Override
>>>> public void initialize(org.opencms.file.CmsObject adminCms,
>>>> org.opencms.configuration.CmsConfigurationManager
>>>> configurationManager,
>>>> CmsModule module) {
>>>>
>>>> LOG.info("Initialisation de la librairie Spring classique
>>>> pour OpenCMS");
>>>>
>>>> try {
>>>> // Configuration des propriétés système
>>>> configureSystemProperties();
>>>>
>>>> // Création du contexte Spring CLASSIQUE
>>>> AnnotationConfigApplicationContext context = new
>>>> AnnotationConfigApplicationContext();
>>>> context.register(com.opencms.library.config.LibraryConfiguration.class);
>>>> context.refresh();
>>>>
>>>> springContext = context;
>>>>
>>>> // Enregistrement des listeners OpenCMS
>>>> OpenCms.addCmsEventListener(this);
>>>>
>>>> LOG.info("Librairie Spring classique initialisée avec
>>>> succès");
>>>>
>>>> } catch (Exception e) {
>>>> LOG.error("Erreur lors de l'initialisation de la
>>>> librairie Spring", e);
>>>> throw new RuntimeException("Impossible d'initialiser la
>>>> librairie Spring", e);
>>>> }
>>>> }
>>>>
>>>> /**
>>>> * Arrêt du module
>>>> */
>>>> @Override
>>>> public void shutDown(CmsModule module) {
>>>> LOG.info("Arrêt de la librairie Spring classique");
>>>>
>>>> if (springContext != null) {
>>>> try {
>>>> if (springContext instanceof
>>>> AnnotationConfigApplicationContext) {
>>>> ((AnnotationConfigApplicationContext)
>>>> springContext).close();
>>>> }
>>>> LOG.info("Contexte Spring fermé avec succès");
>>>> } catch (Exception e) {
>>>> LOG.error("Erreur lors de l'arrêt du contexte
>>>> Spring", e);
>>>> } finally {
>>>> springContext = null;
>>>> }
>>>> }
>>>> }
>>>>
>>>> /**
>>>> * Gestion des événements OpenCMS
>>>> */
>>>> @Override
>>>> public void cmsEvent(CmsEvent event) {
>>>> switch (event.getType()) {
>>>> case I_CmsEventListener.EVENT_PUBLISH_PROJECT:
>>>> LOG.debug("Événement de publication détecté");
>>>> break;
>>>> case I_CmsEventListener.EVENT_CLEAR_CACHES:
>>>> LOG.debug("Événement de nettoyage des caches détecté");
>>>> break;
>>>> }
>>>> }
>>>>
>>>> /**
>>>> * Configuration des propriétés système
>>>> */
>>>> private void configureSystemProperties() {
>>>> // Configuration de base de données (valeurs par défaut)
>>>> if (System.getProperty("spring.datasource.url") == null) {
>>>> System.setProperty("spring.datasource.url",
>>>> "jdbc:postgresql://postgres-db:5432/libdb");
>>>> }
>>>> if (System.getProperty("spring.datasource.username") == null) {
>>>> System.setProperty("spring.datasource.username", "appuser");
>>>> }
>>>> if (System.getProperty("spring.datasource.password") == null) {
>>>> System.setProperty("spring.datasource.password",
>>>> "apppassword");
>>>> }
>>>>
>>>> LOG.info("Propriétés système configurées");
>>>> }
>>>>
>>>> /**
>>>> * Accès aux beans Spring
>>>> */
>>>> public static <T> T getBean(Class<T> beanClass) {
>>>> if (springContext == null) {
>>>> throw new IllegalStateException("Le contexte Spring
>>>> n'est pas initialisé");
>>>> }
>>>> return springContext.getBean(beanClass);
>>>> }
>>>>
>>>> public static Object getBean(String beanName) {
>>>> if (springContext == null) {
>>>> throw new IllegalStateException("Le contexte Spring
>>>> n'est pas initialisé");
>>>> }
>>>> return springContext.getBean(beanName);
>>>> }
>>>>
>>>> public static boolean isSpringContextAvailable() {
>>>> return springContext != null;
>>>> }
>>>> }
>>>>
>>>> If i build this lib as a jar and put it in WEB-INF/lib i can access
>>>> my beans in jsp pages but i must do this call first:
>>>>
>>>> com.opencms.library.integration.LibraryInitializer
>>>> initializer =
>>>> new
>>>> com.opencms.library.integration.LibraryInitializer();
>>>>
>>>> // Appel direct de initialize avec des paramètres nulls
>>>> (notre version simplifiée les gère)
>>>> initializer.initialize(null, null, null);
>>>> after that my context is initialized and configured and my jsp are
>>>> running fine. But the way to automatic loading of my context seems
>>>> to be an opencms module.
>>>>
>>>> I tried to adapt my lib with opencms-module.xml, manifest.xml,...
>>>> but nothing works: at startup
>>>> com.opencms.library.integration.LibraryInitializer is not found by
>>>> opencms.
>>>>
>>>> Can you help me?
>>>> Does it exist a tutorial or how-to?
>>>>
>>>> Am i wrong with public class LibraryInitializer extends
>>>> A_CmsModuleAction implements I_CmsEventListener ?
>>>>
>>>> Thank you
>>>>
>>>> Kind regards,
>>>>
>>>> Laurent
>>>>
>>>>
>>>> _______________________________________________
>>>> This mail is sent to you from the opencms-dev mailing list
>>>> To change your list options, or to unsubscribe from the list,
>>>> please visit
>>>> https://lists.opencms.org/mailman/listinfo/opencms-dev
>>>>
>>>>
>>>>
>>>
>>> _______________________________________________
>>> This mail is sent to you from the opencms-dev mailing list
>>> To change your list options, or to unsubscribe from the list, please
>>> visit
>>> https://lists.opencms.org/mailman/listinfo/opencms-dev
>>>
>>>
>>>
>> --
>> Michael Emmerich
>> Alkacon Software GmbH & Co. KG - The OpenCms Experts
>> http://www.alkacon.com
>> http://www.opencms.org
>>
>> _______________________________________________
>> This mail is sent to you from the opencms-dev mailing list
>> To change your list options, or to unsubscribe from the list, please
>> visit
>> https://lists.opencms.org/mailman/listinfo/opencms-dev
>>
>>
>>
>
>
> _______________________________________________
> This mail is sent to you from the opencms-dev mailing list
> To change your list options, or to unsubscribe from the list, please visit
> https://lists.opencms.org/mailman/listinfo/opencms-dev
>
>
>
--
Michael Emmerich
-------------------
Alkacon Software GmbH & Co. KG - The OpenCms Experts
Michael Emmerich
An der Wachsfabrik 13
50996 Koeln, DE
Tel: +49 (0)2236 3826-14
Fax: +49 (0)2236 3826-20
Email:m.emmerich at alkacon.com
http://www.alkacon.com
http://www.opencms.org
Amtsgericht Köln, HRA 32185, USt-IdNr.: DE259882372
Vertreten durch: Alkacon Verwaltungs GmbH
Geschäftsführer: Alexander Kandzior, Amtsgericht Köln, HRB 88218
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.opencms.org/pipermail/opencms-dev/attachments/20250812/afb7e407/attachment.htm>
More information about the opencms-dev
mailing list