Package org.apache.sling.extensions.gwt.sample.server

Source Code of org.apache.sling.extensions.gwt.sample.server.NotesServiceImpl

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sling.extensions.gwt.sample.server;

import java.util.ArrayList;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.extensions.gwt.sample.service.Note;
import org.apache.sling.extensions.gwt.sample.service.NotesService;
import org.apache.sling.extensions.gwt.user.server.rpc.SlingRemoteServiceServlet;
import org.apache.sling.jcr.api.SlingRepository;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* This class implements a servlet-based RPC remote service for handling RPC calls from the GWT client application.
* <p/>
* It registers as an OSGi service and component, under the <code>javax.servlet.Servlet</code> interface. It thus
* acts as a servlet, registered under the path specified  by the <code>sling.servlet.paths</code> scr property.
* The path under which the servlet is registered must correspond to the GWT module's base url.
* <p/>
* The NotesServiceImpl class handles the creation, retrieval and deletion of {@link Note}s, as POJOs and as
* <code>javax.jcr.Node</code>s in the repository.
* <p/>
* The class is an implementation of the <code>SlingRemoteServiceServlet</code> and is as such able to handle
* GWT RPC calls in a Sling environment. The servlet must be registered with the GWT client application in the
* <code>Notes.gwt.xml</code> module configuration file.
*
*/
@Component
@Service(value=javax.servlet.Servlet.class)
@Property(name="sling.servlet.paths", value="/gwt/org.apache.sling.extensions.gwt.sample.Notes/notesservice")
public class NotesServiceImpl extends SlingRemoteServiceServlet implements NotesService {

    /**
     * The logging facility.
     */
    private static final Logger log = LoggerFactory.getLogger(NotesServiceImpl.class);

    /**
     * The <code>String</code> constant representing the name of the <code>javax.jcr.Property</code> in which the
     * title of a note is stored.
     */
    private static final String PN_NOTETITLE = "noteTitle";

    /**
     * The <code>String</code> constant representing the name of the <code>javax.jcr.Property</code> in which the
     * text of a note is stored.
     */
    private static final String PN_NOTETEXT = "noteText";

    /**
     * The <code>String</code> constant representing the name of the path in the repository under which the notes are
     * stored.
     */
    private static final String PATH_DEMOCONTENT = "/gwt/demo/notes";

    /**
     * This is the <code>SlingRepository</code> as provided by the Sling environment. It is used for repository
     * access/operations.
     *
     */
    @Reference
    private SlingRepository repository;

    /**
     * This is the <code>javax.jcr.Session</code> used for repository operations. It is retrieved from the repository
     * through an administrative login.
     */
    private Session session;

    /**
     * The <code>javax.jcr.Node</code> representing the root of the demo content. See {@link NotesServiceImpl#repository}.
     */
    private Node root;

    /**
     * This is the OSGi component/service activation method. It initializes this service.
     *
     * @param context The OSGi context provided by the activator.
     */
    protected void activate(ComponentContext context) {
        /**
         * GWT normally uses Thread.getCurrentThread().getContextClassLoader() as its class loader. This is illegal
         * in the OSGi environment, as GWT then cannot access the service implementation classes of this bundle
         * during an RPC call. As such we have explicitly hand over our bundle's class loader to GWT. For this purpose
         * this class extends <code>SlingRemoteServiceServlet</code> instead of only GWT's <code>RemoteServiceServlet</code>.
         * The <code>SlingRemoteServiceServlet</code> has been extended to set a correct classloader and to provide
         * resources via bundles.
         */
        super.setClassLoader(this.getClass().getClassLoader());
        super.setBundle(context.getBundleContext().getBundle());
        log.info("activate: initialized and provided classloader {} to GWT.", this.getClass().getClassLoader());

        try {
            // retrieve a session from the repository
            session = repository.loginAdministrative(repository.getDefaultWorkspace());
        } catch (RepositoryException e) {
            log.error("activate: repository unavailable: " + context + ": ", e);
        }

        try {
            // get the demo content root node from the session
            root = (Node) session.getItem(PATH_DEMOCONTENT);
        } catch (RepositoryException e) {
            log.error("activate: error while getting demo content path " + PATH_DEMOCONTENT + ": "
                    + session.getWorkspace().getName() + ": ", e);
        }
    }

    /**
     * {@inheritDoc}
     */
    public String createNote(Note note) {

        String message = "The note was successfully created!";

        log.info("createNote: creating note with title {}...", note.getTitle());
        if (root != null) {
            try {

                // add a node to the root of the demo content and set the properties via the POJO's getters
                final Node node = root.addNode("note");
                node.setProperty(PN_NOTETITLE, note.getTitle());
                node.setProperty(PN_NOTETEXT, note.getText());
                root.save();
                log.info("createNote: successfully saved note {} to repository.", node.getPath());

            } catch (RepositoryException e) {

                log.error("createNote: error while creating note in repository: ", e);
                message = "Failed to create note! Error: " + e.getMessage();
                try {
                    // if the node creation failed, try to roll-back the repository changes accumulated
                    if (session.hasPendingChanges()) {
                        session.refresh(false);
                    }
                } catch (RepositoryException e1) {
                    log.error("createNote: error while reverting changes after trying to save note to repository: ", e1);
                    message = "Failed to create note! Error: " + e1.getMessage();
                }
            }

        } else {
            log.error("createNote: cannot create note, demo content path {} unavailable!", PATH_DEMOCONTENT);
            message = "Failed to create note! Error: demo content path unavailable";
        }

        return message;
    }

    /**
     * {@inheritDoc}
     */
    public ArrayList<Note> getNotes() {

        final ArrayList<Note> notes = new ArrayList<Note>();

        if (root != null) {
            try {

                // get all child nodes of the demo content root node
                final NodeIterator nodes = root.getNodes();
                while (nodes.hasNext()) {

                    Node node = nodes.nextNode();
                    // for every child node, that has the correct properties set, create a POJO and add it to the list
                    if (node.hasProperty(PN_NOTETITLE) && node.hasProperty(PN_NOTETEXT)) {

                        final Note note = new Note();
                        note.setTitle(node.getProperty(PN_NOTETITLE).getString());
                        note.setText(node.getProperty(PN_NOTETEXT).getString());
                        // set the node's path, so that the GWT client app can use it as the parameter for the
                        // deleteNote(String path) method.
                        note.setPath(node.getPath());

                        notes.add(note);
                        log.info("getNotes: found note {}, adding to list...", node.getPath());
                    }
                }

            } catch (RepositoryException e) {
                log.error("getNotes: error while getting list of notes from " + PATH_DEMOCONTENT + ": ", e);
            }

        } else {
            log.error("getNotes: error while getting notes, demo content path {} unavailable!", PATH_DEMOCONTENT);
        }

        return notes;
    }

    /**
     * {@inheritDoc}
     */
    public String deleteNote(String path) {

        String message = "The note was successfully deleted!";

        try {
            session.getItem(path).remove();
            session.save();
        } catch (RepositoryException e) {
            log.error("deleteNote: error while deleting note {}: ", e);
            message = "Failed to delete to note! Error: " + e.getMessage();
        }

        return message;
    }
}
TOP

Related Classes of org.apache.sling.extensions.gwt.sample.server.NotesServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.