CRM and CX Blogs by Members
Find insights on SAP customer relationship management and customer experience products in blog posts from community members. Post your own perspective today!
cancel
Showing results for 
Search instead for 
Did you mean: 
StefanKruk
Active Participant

Introduction:


In a Project, we faced the Issue that sometimes when we minimized JavaScript HTML was appended which leads to no longer valid JavaScript File and therefore browsers not evaluating JavaScript.

 

In this blog post, I want to explain the behavior and the reason for this problem, as well as how we solve this problem.

 

Behavior Explanation


Wro4j


Wro4j is configured via wro.xml see (https://wro4j.readthedocs.io/en/stable/WroFileFormat/). There the Javascript files and CSS files are defined which should be minimized. Wro4j also supports the possibility to load Resources via wildcard (https://wro4j.readthedocs.io/en/stable/WildcardSupport/)

To load the resources there are multiple Resource Locators available (https://wro4j.readthedocs.io/en/stable/ResourceTypes/). Based on conventions and definition in wro.xml.

The default behavior is to use the ServletContextUriLocator which will look for the resources via the dispatcher. If the File(s) cannot be loaded it will be tried to load them from extern with the current request context.

This is a feature of Wro4j to also provide the possibility to load external resources. For this, the UrlUriLocater will be used. In this locator, it is checked if the URL is a wildcard. Unfortunately, the check is working with a flag "enableWildcards" which is initialized with false (https://github.com/wro4j/wro4j/blob/v1.9.0/wro4j-core/src/main/java/ro/isdc/wro/model/resource/locat...)
enableWildcards && super.hasWildcard(uri);

The second problem is that the Super method "hasWildcard" is working with a pattern that also returns false if "HTTP" is part of the URL (https://github.com/wro4j/wro4j/blob/b09a44747011006578d3a916fa464a39f633e860/wro4j-core/src/main/jav...).
/**
* Character to distinguish wildcard inside the uri. If the file name contains '*' or '?' character, it is considered
* a wildcard.
* <p>
* A string is considered to contain wildcard if it doesn't start with http(s) and contains at least one of the
* following characters: [?*].
*/
private static final String WILDCARD_REGEX = "^(?:(?!http))(.)*[\\*\\?]+(.)*";

Therefore following URI is used for retrieving the external Resource:

https://localhost:9002/all_responsive.js/_ui/responsive/common/js/cms/*.js


Hybris


In Hybris the default Behavior for not found Pages is to display a custom 404 pages. This is necessary to display a pretty Page to the user.

The wro.xml config from Hybris OOTB looks like this:
<!--
Copyright (c) 2019 SAP SE or an SAP affiliate company. All rights reserved.
-->
<groups xmlns="http://www.isdc.ro/wro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.isdc.ro/wro wro.xsd">

<import>classpath:wro_addons.xml</import>


<group name="alpha_responsive">
<css>/_ui/responsive/theme-alpha/css/style.css</css>
</group>


<group name="lambda_responsive">
<css>/_ui/responsive/theme-lambda/css/style.css</css>
</group>

<group name="all_responsive">

<!-- jquery -->
<js minimize="false">/_ui/responsive/common/js/jquery-3.2.1.min.js</js>

<!-- plugins -->
<js minimize="false">/_ui/responsive/common/js/enquire.min.js</js>
<js>/_ui/responsive/common/js/Imager.min.js</js>
<js minimize="false">/_ui/responsive/common/js/purify.min.js</js>
<js>/_ui/responsive/common/js/jquery.blockUI-2.66.js</js>
<js minimize="false">/_ui/responsive/common/js/jquery.colorbox-min.js</js>
<js minimize="false">/_ui/responsive/common/js/jquery.form.min.js</js>
<js>/_ui/responsive/common/js/jquery.hoverIntent.js</js>
<js>/_ui/responsive/common/js/jquery.pstrength.custom-1.2.0.js</js>
<js>/_ui/responsive/common/js/jquery.syncheight.custom.js</js>
<js>/_ui/responsive/common/js/jquery.tabs.custom.js</js>
<js minimize="false">/_ui/responsive/common/js/jquery-ui-1.12.1.min.js</js>
<js>/_ui/responsive/common/js/jquery.zoom.custom.js</js>
<js>/_ui/responsive/common/js/owl.carousel.custom.js</js>
<js minimize="false">/_ui/responsive/common/js/jquery.tmpl-1.0.0pre.min.js</js>
<js minimize="false">/_ui/responsive/common/js/jquery.currencies.min.js</js>

<!-- Custom ACC JS -->
<js>/_ui/responsive/common/js/acc.address.js</js>
<js>/_ui/responsive/common/js/acc.autocomplete.js</js>
<js>/_ui/responsive/common/js/acc.carousel.js</js>
<js>/_ui/responsive/common/js/acc.cart.js</js>
<js>/_ui/responsive/common/js/acc.cartitem.js</js>
<js>/_ui/responsive/common/js/acc.checkout.js</js>
<js>/_ui/responsive/common/js/acc.checkoutsteps.js</js>
<js>/_ui/responsive/common/js/acc.cms.js</js>
<js>/_ui/responsive/common/js/acc.colorbox.js</js>
<js>/_ui/responsive/common/js/acc.common.js</js>
<js>/_ui/responsive/common/js/acc.forgottenpassword.js</js>
<js>/_ui/responsive/common/js/acc.global.js</js>
<js>/_ui/responsive/common/js/acc.hopdebug.js</js>
<js>/_ui/responsive/common/js/acc.imagegallery.js</js>
<js>/_ui/responsive/common/js/acc.langcurrencyselector.js</js>
<js>/_ui/responsive/common/js/acc.minicart.js</js>
<js>/_ui/responsive/common/js/acc.navigation.js</js>
<js>/_ui/responsive/common/js/acc.order.js</js>
<js>/_ui/responsive/common/js/acc.paginationsort.js</js>
<js>/_ui/responsive/common/js/acc.payment.js</js>
<js>/_ui/responsive/common/js/acc.paymentDetails.js</js>
<js>/_ui/responsive/common/js/acc.pickupinstore.js</js>
<js>/_ui/responsive/common/js/acc.product.js</js>
<js>/_ui/responsive/common/js/acc.productDetail.js</js>
<js>/_ui/responsive/common/js/acc.quickview.js</js>
<js>/_ui/responsive/common/js/acc.quote.js</js>
<js>/_ui/responsive/common/js/acc.consent.js</js>
<js>/_ui/responsive/common/js/acc.cookienotification.js</js>
<js>/_ui/responsive/common/js/acc.closeaccount.js</js>
<js>/_ui/responsive/common/js/acc.ratingstars.js</js>
<js>/_ui/responsive/common/js/acc.refinements.js</js>
<js>/_ui/responsive/common/js/acc.sanitizer.js</js>
<js>/_ui/responsive/common/js/acc.silentorderpost.js</js>
<js>/_ui/responsive/common/js/acc.tabs.js</js>
<js>/_ui/responsive/common/js/acc.termsandconditions.js</js>
<js>/_ui/responsive/common/js/acc.track.js</js>
<js>/_ui/responsive/common/js/acc.storefinder.js</js>
<js>/_ui/responsive/common/js/acc.futurelink.js</js>
<js>/_ui/responsive/common/js/acc.productorderform.js</js>
<js>/_ui/responsive/common/js/acc.savedcarts.js</js>
<js>/_ui/responsive/common/js/acc.multidgrid.js</js>
<js>/_ui/responsive/common/js/acc.quickorder.js</js>
<js>/_ui/responsive/common/js/acc.csv-import.js</js>
<js>/_ui/responsive/common/js/_autoload.js</js>

<!-- Cms Action JavaScript files -->
<js>/_ui/responsive/common/js/cms/*.js</js>
</group>

</groups>

The Wildcard line
<js>/_ui/responsive/common/js/cms/*.js</js>

is necessary to load additional JavaScripts from Components and/or other Storefront addons and therefore is part of how the Storefront customization works.

The Problem


In the wro.xml the following wildcard is defined:
<js>/_ui/responsive/common/js/cms/*.js</js>

If no files exist in the cms folder it will be tried to load them via external locator, which results in a URI like this:

https://localhost:9002/all_responsive.js/_ui/responsive/common/js/cms/*.js

Unfortunately, if a page is called that does not exist in hybris, the custom 404 Page is returned with code 200 (OK) instead of HTTP Status 404 (NOT FOUND). (see de.hybris.platform.yacceleratorstorefront.controllers.pages.DefaultPageController.java#get)

This leads to wro4j to use the response (in form of the 404 page HTML) and append them to the minimized JavaScript.

 

Possible Solutions



  1. Add the prefix "classpath" to the resources URLs
    <js>classpath:_ui/responsive/common/js/cms/*.js</js>​

    to indicate that this line should only be interpreted by the ClasspathUriLocator.
    This solution is the quickest but not the longest one, as the problem could reoccur if resources cannot be found locally (maybe deleted as they are no longer necessary or were refactored).



  1. Modify web.xml to prevent javascript and css files going through DispatcherServlet
    <filter-mapping>
    <filter-name>resourceFilter</filter-name>
    <url-pattern>/_ui/*</url-pattern>
    <url-pattern>*.js</url-pattern>
    <url-pattern>*.css</url-pattern>
    </filter-mapping>
    ..
    <serverl-mapping>
    <servlet-name>DefaultServletAdapter</servlet-name>
    ...
    <url-pattern>*.js</url-pattern>
    <url-pattern>*.css</url-pattern>
    </servlet-mapping>​




  1. Change the Storefront Implementation so that the custom 404 Page also returns the HTTP Status Code 404.