no code liferay
Ashil Vaishnani

Error Reporting: Email Notifications In Liferay

In this blog, we'll explore how to enhance error reporting in Liferay. By leveraging this customization, we aim to establish a robust system that not only detects errors but also takes proactive measures to notify relevant stakeholders. This entails the automatic generation of email notifications, which will be dispatched to specific users or developers whenever an error is encountered and displayed. This streamlined approach to error reporting not only ensures timely awareness but also facilitates swift action and resolution, ultimately enhancing the overall stability and performance of the Liferay environment.

Here we will walk you through the process of setting up error reporting specifically for portlet errors, which are among the most common issues encountered in Liferay. To achieve this, we'll make modifications to the portlet_error.jsp file. Since this file is part of the portal core, the best practice for customization is through the CustomJspBag module.

Below is a concise walkthrough on setting up a custom JSP bag to accomplish this task.

1. In your module, create a class that implements CustomJspBag.


    @Component(
    immediate = true,
    property = {
    "context.id=StockfishCustomJspBag", "context.name=Stockfish Custom JSP Bag",
    "service.ranking:Integer=100"
    }
    )
    public class StockfishCustomJspBag implements CustomJspBag {
    }
                                        

2. Implement the getCustomJspDir method to return the folder path in your module’s JAR where the JSPs reside.

    @Override
    public String getCustomJspDir() {
        return "META-INF/jsps/";
    }
    @Override
    public boolean isCustomJspGlobal() {
        return true;
    }
                             

3. Create an activate method and the following fields. The method adds the URL paths of all your custom JSPs to a list when the module is activated.

    @Activate
    protected void activate(BundleContext bundleContext) {
        _bundle = bundleContext.getBundle();

        _customJsps = new ArrayList<>();

        Enumeration<URL> entries = _bundle.findEntries(
            getCustomJspDir(), "*.jsp", true);

        while (entries.hasMoreElements()) {
            URL url = entries.nextElement();
            _customJsps.add(url.getPath());
        }
    }

    @Override
    public List getCustomJsps() {
        return _customJsps;
    }

    private Bundle _bundle;

    private List _customJsps;
    
                            

4. Implement the getURLContainer method to return a com.liferay.portal.kernel.url.URLContainer.

    @Override
    public URLContainer getURLContainer() {
        return _urlContainer;
    }
    
    private final URLContainer _urlContainer = new URLContainer() {
        @Override
        public URL getResource(String name) {
            return _bundle.getEntry(name);
        }
    
        @Override
        public Set<String> getResources(String path) {
            Set<String> paths = new HashSet<>();
            for (String entry : _customJsps) {
                if (entry.startsWith(path)) {
                    paths.add(entry);
                }
            }
            return paths;
        }
    };
                            

Once we've integrated the CustomJspBag for the portlet_error.jsp, our module structure takes on a new configuration.

    Stockfish-custom-jsp-bag
        └── src
            ├── java
            │   └── com.stockfish.custom.jsp.bag
            │       └── StockfishCustomJspBag.java
            └── resources
                ├── META-INF
                    └── jsp
                        └── html
                            └── portal
                                └── portlet_error.jsp
                            

Whenever an error occurs in the Portlet, the system will trigger email notifications to specific users. To implement this feature, we must set up a system configuration to gather users' email addresses, allowing us to send them notifications in case of errors.

To achieve this, we've defined an EmailNotificationsConfiguration class, which manages these settings.

    @ExtendedObjectClassDefinition(
        category = "stockfish",
        scope = ExtendedObjectClassDefinition.Scope.SYSTEM
    )
    @Meta.OCD(
        id = "com.stockfish.test.configuration.EmailNotificationsConfiguration",
        localization = "content/Language",
        name = "sending-email-for-not-displaying-mvcportlet"
    )
    public interface EmailNotificationsConfiguration {
    @Meta.AD(deflt = "", name = "Email-Address", required = false)
    public String emailAddress();
    }
                            
    @Component(service = ConfigurationCategory.class)
    public class SystemConfigurationCategory implements ConfigurationCategory {
    @Override
    public String getCategoryIcon() {
        return "plug";
    }
    @Override
    public String getCategoryKey() {
        return "stockfish";
    }
    @Override
    public String getCategorySection() {
        return "other";
    }
    }
                            
Created system configuration is look like below:

We can utilize both RestAPI and MVCResourceCommand to send email notifications. In this context, we'll focus on using MVCResourceCommand for sending email notifications.


Now we are going to create a class that implements MVCResouceCommand. In this class, we'll write code to retrieve email addresses from the system configuration and send email notifications to the specified users whenever an error occurs in the Portlet.


    @Component(
        immediate = true,
        configurationPid ="com.stockfish.test.configuration.EmailNotificationsConfiguration",
        property = {
                "javax.portlet.name=" + TestPortletKeys.TEST,
                "mvc.command.name=sendingEmail"
        },
        service = MVCResourceCommand.class
    )
    public class SendingEmailMVCResource implements MVCResourceCommand {
        @Override
        public boolean serveResource(ResourceRequest resourceRequest, ResourceResponse resourceResponse) throws PortletException {

            // ToDo: write a code for sending an email

        }
    }
                            

We'll trigger this resourceCommand whenever an error is detected.


To accomplish this, we'll invoke the resourceCommand when the portlet_error.jsp is loaded, using the resource URL as demonstrated below.


    <script>
        $(document).ready(function() {
            var basePortletURL = window.location.href;
            var resourceURL = Liferay.Util.PortletURL.createResourceURL(
                basePortletURL,
                {
                'p_p_id': 'com_stockfish_test_TestPortlet',
                'p_p_resource_id': 'sendingEmail',
                }
            );
        
        
                $.ajax({
                    url: resourceURL,
                    type: 'POST',
                    success: function(data) {
                        console.log("Export URL called successfully");
                    },
                    error: function(xhr, status, error) {
                        console.error("Error calling export URL: " + error);
                    }
                });
        });
    <script>
                    

That's it !! We've just completed the integration of email notifications to alert us when portlet errors occur. This addition will help us stay on top of issues and respond quickly, improving overall system reliability. With these notifications in place, our response time to portlet errors will be much faster.




For comprehensive business solutions and in-depth insights into Error reporting framework, connect with us at info@stockfish.app to unlock the full potential of your digital platform.

Send us a message

Thank you! One of our representative will contact you soon. :)
Something went wrong. Please contact us at info@stockfish.app

Contact us

Ready to transform your digital ideas into reality? At Stockfish, we specialize in crafting exceptional web and mobile applications. Let's collaborate to bring your vision to life. Fill out the form, and we'll get back to you promptly to discuss how we can assist you in achieving your digital goals. Your success is our priority.

Let's make something beautiful together.

C-309, Titanium Business Park, Ahmedabad 380051, India