Tapestry 4: Asset cache management?

I use Tapestry 4, and whenever we click on a release that changes any assets (image, stylesheet, JS library), we get problems because users still have the old version of the asset in the browser cache. I would like to create an easy way to enable caching, but when loading a new application, force a new asset to be loaded. Simply prohibiting caching completely for assets is not an acceptable solution.

I could not see any existing mechanism for this, but I decided that there might be some way to tell Tapestry to add the assembly number to the URL like this:

http://www.test.com/path/to/the/asset/asset.jpg?12345

Thus, each new assembly will make it look like a different asset for the end user.

Does Tapestry provide an easy way to solve a cache problem that I don't know about? If not, how can I change the URL generated by Tapestry? And how will the code responsible for this get the build number? (I could, for example, get the build number in the Spring bean, but how will the new URL building mechanism get on it?)

+3
source share
1 answer

After a long suppression of this problem, I eventually solved it myself. This solution assumes that your project has a spring tapestry library .

In my case, I have a Spring bean that contains some of my global application properties:

package myapp;

public class AppProperties {
    private String build;

    public String getBuild() {
        return build;
    }

    public void setBuild(String build) {
        this.build = build;
    }

    // other properties
}

Declare this bean in the Spring configuration:

<bean id="appProperties" class="myapp.AppProperties">
    <property name="build" value="@BUILD_NUMBER@"/>
</bean>

Ant build script @BUILD_NUMBER@ (. Copy Ant).

, IAsset URL-:

package myapp;

import java.io.InputStream;

import org.apache.hivemind.Location;
import org.apache.hivemind.Resource;
import org.apache.tapestry.IAsset;

public class BuildAwareAssetWrapper implements IAsset {
    private IAsset wrapped;
    private String build;

    public BuildAwareAssetWrapper(IAsset wrapped, String build) {
        this.wrapped = wrapped;
        this.build = build;
    }

    public String buildURL() {
        return addParam(wrapped.buildURL(), "build", build);
    }

    public InputStream getResourceAsStream() {
        return wrapped.getResourceAsStream();
    }

    public Resource getResourceLocation() {
        return wrapped.getResourceLocation();
    }

    public Location getLocation() {
        return wrapped.getLocation();
    }

    private static String addParam(String url, String name, String value) {
        if (url == null) url = "";
        char sep = url.contains("?") ? '&' : '?';
        return url + sep + name + '=' + value;
    }
}

, Tapestry . AssetSourceImpl IAsset . findAsset(), -:

package myapp;

import java.util.Locale;

import org.apache.hivemind.Location;
import org.apache.hivemind.Resource;
import org.apache.tapestry.IAsset;
import org.apache.tapestry.asset.AssetSourceImpl;

public class BuildAwareAssetSourceImpl extends AssetSourceImpl {
    private AppProperties props;

    @Override
    public IAsset findAsset(Resource base, String path, Locale locale, Location location) {
        IAsset asset = super.findAsset(base, path, locale, location);
        return new BuildAwareAssetWrapper(asset, props.getBuild());
    }

    public void setAppProperties(AppProperties props) {
        this.props = props;
    }
}

, , Spring bean. - Tapestry BuildAwareAssetSourceImpl AssetSourceImpl. , hivemodule.xml:

<!-- Custom asset source -->
<implementation service-id="tapestry.asset.AssetSource">
    <invoke-factory service-id="hivemind.BuilderFactory" model="singleton">
        <construct class="myapp.BuildAwareAssetSourceImpl">
            <set-object property="appProperties" value="spring:appProperties"/>
            <set-configuration property="contributions" configuration-id="tapestry.asset.AssetFactories"/>
            <set-service property="lookupAssetFactory" service-id="tapestry.asset.LookupAssetFactory"/>
            <set-service property="defaultAssetFactory" service-id="tapestry.asset.DefaultAssetFactory"/>
        </construct>
    </invoke-factory>
</implementation>

. , , , URL- build.

+6

Source: https://habr.com/ru/post/1699533/


All Articles