Adriano
Adriano

Reputation: 20041

Magnolia CMS: renaming page creates 404 when using Urltrans module

Urltrans module helps me to have internationalized URLs, but a single hierarchy.


Overall it works fine, except in that case:

  1. Back in Magnolia CMS admin central, in the pages app, open a page
  2. Let's say that I'm visualizing the page the page in German
  3. Open the Page Properties Dialog
  4. Change the (Localized) name
  5. Save
  6. 404 error message in the "Page Preview" tab. The log says 2016-11-01 11:17:57,413 WARN info.magnolia.rendering.engine.RenderingFilter : Resource not found: [/<path>/<to>/<page>?mgnlPreview=false&mgnlChannel=desktop]

This happens simply because the page that I am now trying to see in admin central is still the one with the "former name", hence the "former url path", hence a page that does not exist anymore.

I found this issue mentioned at line 51 of UrltransSaveHandler.java (I think that's what I mean).

Any idea how I could prevent this from happening, for instance:

Upvotes: 1

Views: 559

Answers (1)

Adriano
Adriano

Reputation: 20041

Explanation

UrltransSaveHandler.java is actually NOT used.

However, the SaveDialogAction.java is configured in the Action Definition on the dialog.

That's the relevant dialog (if you have not overridden it): admincentral#app:configuration:browser;/modules/standard-templating-kit/dialogs/generic/master/basePageProperties:treeview:.

SaveDialogAction.java calls setNodeName(node, item) at line 81.

This method is very similar to what was happening at line 51 of UrltransSaveHandler.java: it does a "if (node's "name" property has changed?){rename node itself}".


Solution: in a nutshell

  1. Create a new Action Definition that does exactly the same as the SaveDialogAction except this call to setNodeName(node, item); that only happens if the parent node is not of NodeType mgnl:variant
  2. Assign this new Class to the Commit Action in the relevant dialog configuration

Action Definition class

package com.myproject.dialog;

import info.magnolia.ui.admincentral.dialog.action.SaveDialogActionDefinition;
import info.magnolia.ui.api.action.Action;

public class MyProjectUrltransSaveActionDefinition extends SaveDialogActionDefinition {

    public MyProjectUrltransSaveActionDefinition() {
        setImplementationClass((Class<? extends Action>) MyProjectUrltransSaveAction.class);
    }

}

Action class

package com.myproject.dialog;

import javax.jcr.Node;
import javax.jcr.nodetype.NodeType;
import javax.jcr.Property;
import javax.jcr.RepositoryException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vaadin.data.Item;

import info.magnolia.cms.core.Path;
import info.magnolia.jcr.util.NodeUtil;
import info.magnolia.ui.admincentral.dialog.action.SaveDialogAction;
import info.magnolia.ui.api.action.ActionExecutionException;
import info.magnolia.ui.form.EditorCallback;
import info.magnolia.ui.form.EditorValidator;
import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter;
import info.magnolia.ui.vaadin.integration.jcr.ModelConstants;


public class MyProjectUrltransSaveAction<T extends MyProjectUrltransSaveActionDefinition> extends SaveDialogAction {

    private static final Logger log = LoggerFactory.getLogger(MyProjectUrltransSaveAction.class);

    public MyProjectUrltransSaveAction(T definition, Item item, EditorValidator validator, EditorCallback callback) {
        super(definition, item, validator, callback);
    }

    public void execute() throws ActionExecutionException {
        if (validateForm()) {
            final JcrNodeAdapter item = (JcrNodeAdapter) this.item;
            try {
                final Node node = item.applyChanges();
                final Node parentNode = node.getParent();
                final String parentNodeType = parentNode.getPrimaryNodeType().getName();
                if(!parentNodeType.equals("mgnl:variant")){
                    setNodeName(node, item);
                }
                node.getSession().save();
            } catch (final RepositoryException e) {
                throw new ActionExecutionException(e);
            }
            callback.onSuccess(getDefinition().getName());
        }
    }

    /**
     * Set the node Name.
     * Node name is set to: <br>
     * the value of the property 'name' if it is present.
     */
    protected void setNodeName(Node node, JcrNodeAdapter item) throws RepositoryException {
        String propertyName = "name";
        if (node.hasProperty(propertyName) && !node.hasProperty(ModelConstants.JCR_NAME)) {
            Property property = node.getProperty(propertyName);
            String newNodeName = property.getString();
            if (!node.getName().equals(Path.getValidatedLabel(newNodeName))) {
                newNodeName = Path.getUniqueLabel(node.getSession(), node.getParent().getPath(), Path.getValidatedLabel(newNodeName));
                item.setNodeName(newNodeName);
                NodeUtil.renameNode(node, newNodeName);
            }
        }
    }

}

Upvotes: 1

Related Questions