[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