Laliwala IT Services

Laliwala IT Services
Website Development

Friday, January 28, 2011

Writing Java-Backed Web Scripts

Writing Java-Backed Web Scripts

liferay tutorial





Step-by-Step: Writing a Java-Backed Web Script.
Here, we explain Java-Backed Web Script with Handling Rating Posts.
· Like the web scripts you've seen so far, this is going to involve a Free Marker Template and a Descriptor.
· But instead of using JavaScript for a Controller you are going to write a Java class.
· To let the web script framework know about the Java class, you'll use a new Spring bean configuration file to declare which web script the controller class belongs to.
· Before we precede look out for difference between 2.2 Enterprise and 3.0 Labs, Alfresco changed some packages and class names in org.alfresco.web.scripts.





























































































































































(Writing Java-Backed Web Scripts
Step-by-Step: Writing a Java-Backed Web Script.
Here, we explain Java-Backed Web Script with Handling Rating Posts.
· Like the web scripts you've seen so far, this is going to involve a Free Marker Template and a Descriptor.
· But instead of using JavaScript for a Controller you are going to write a Java class.
· To let the web script framework know about the Java class, you'll use a new Spring bean configuration file to declare which web script the controller class belongs to.
· Before we precede look out for difference between 2.2 Enterprise and 3.0 Labs, Alfresco changed some packages and class names in org.alfresco.web.scripts.
Follow these steps:
1. First, create the descriptor. This script handles the POST method, so name the descriptor rating.post.desc.xml and populate it as follows:
Post Content Rating
Sets rating data for the specified node
/someco/rating
/someco/rating.json
/someco/rating.html
extension
guest
requiresnew
2. Second, create the HTML response template called rating.post.html.ftl.
(The response templates simply echo back the node, rating, and user argument values that were used to create the new rating.)
Successfully added rating:

Node:${node}

Rating:${rating}

User:${user}

Show rating

3. Then, create the JSON response template called rating.post.json.ftl:
{"rating" :
{
"node" : "${node}",
"rating" : "${rating}",
"user" : "${user}"
}
}
4. Now write the Java code.
1. First, write the business logic for creating the rating.
2. Just as you did in the JavaScript-based controller when you put the business logic in the rating.js file to promote reuse, you're going to use the Rating bean you created in an earlier chapter for the new create() method. The class is com.someco.behavior.Rating.
3. Begin the new method by accepting the NodeRef of the Whitepaper, the rating value, and the user posting the rating as arguments.
5. First, implement the web script's controller logic. All you have to do is write a Java class that grabs the ID, rating, and user arguments and then creates the new rating node. To do that, create a new class in src|java called
com.someco.scripts.PostRating.
The class must extend org.alfresco.web.scripts.DeclarativeWebScript
public class PostRating extends org.alfresco.web.scripts.
DeclarativeWebScript {
6. The Node Service will be injected as a dependency by Spring:
private NodeService nodeService;
7. The controller logic goes in the executeImpl() method. The first thing you need to do after declaring the method is initialize the ratingValue variable and grab the ID, rating, and user arguments:
@Override
protected Map executeImpl(WebScriptRequest req,
WebScriptStatus status) {
int ratingValue = -1;
String id = req.getParameter("id");
String rating = req.getParameter("rating");
String user = req.getParameter("user");
8. Next, attempt to parse the rating value. If an exception is thrown, move forward with the initialized value, which will get caught during the
range check:
try {
ratingValue = Integer.parseInt(rating);
} catch (NumberFormatException nfe) {
}
9. The parameters are all required.
· Web scripts do not yet enforce mandatory arguments. So the controller does the checking and sets an error code if there is a problem.
· If all arguments have been provided and the rating is in the range we are looking for, grab the NodeRef based on the ID passed in, check with the nodeService to make sure it exists, and then call the create() method that you will implement shortly:
if (id == null || rating == null || user == null) {
logger.debug("ID, rating, or user not set");
status.setCode(Status.STATUS_BAD_REQUEST, "Required data has not been provided");
} else if ((ratingValue <> 5)) {
logger.debug("Rating out of range");
status.setCode(Status.STATUS_BAD_REQUEST, "Rating value must be between 1 and 5 inclusive");
} else {
logger.debug("Getting current node");
NodeRef curNode = new NodeRef("workspace://SpacesStore/" + id);
if (!nodeService.exists(curNode)) {
logger.debug("Node not found");
status.setCode(Status.STATUS_NOT_FOUND, "No node found for id:" + id);
} else {
// Refactored to use the Rating Service
//create(curNode, Integer.parseInt(rating), user);
ratingService.rate(curNode, Integer.parseInt(rating), user);
}}
10. The rating data that was passed in needs to set on the model so that it can be echoed back by the response templates:
Map model = new HashMap();
model.put("node", id);
model.put("rating", rating);
model.put("user", user);
return model;
}
11. Now implement the create() method. This method uses the runAs method in AuthenticationUtil so that regardless of the permissions of the authenticated user running the web script, the rating node will get created:
public void create(final NodeRef nodeRef, final int rating,
final String user) {
AuthenticationUtil.runAs(new RunAsWork() {
@SuppressWarnings("synthetic-access")
public String doWork() throws Exception {
12. The method should first ask the nodeService if the Whitepaper already
has the rateable aspect. If it does, no action is necessary, otherwise, add
the aspect:
// add the aspect to this document if it needs it
if (nodeService.hasAspect(nodeRef, SomeCoModel.ASPECT_
SC_RATEABLE)) {
} else {
nodeService.addAspect(nodeRef, SomeCoModel.ASPECT_
SC_RATEABLE, null);
}
13. Create a new properties map to store the rating and rater properties:
Map props = new HashMap
Serializable>();
props.put(SomeCoModel.PROP_RATING, rating);
props.put(SomeCoModel.PROP_RATER, user);
14. Use the node service to create a new ratings node as a child to the Whitepaper, then close out the method:
nodeService.createNode(
nodeRef,
SomeCoModel.ASSN_SC_RATINGS,
QName.createQName(SomeCoModel.NAMESPACE_
SOMECO_CONTENT_MODEL, SomeCoModel.PROP_RATING.
getLocalName() + new Date().getTime()),
SomeCoModel.TYPE_SC_RATING,
props);
return "";
}
},
"admin");
}
15. Complete the class by adding a setter for the nodeService:
public void setNodeService(NodeService nodeService) {
this.nodeService = nodeService;
}
}
16. Save the class.
17. You need to tweak the Rating behavior class. When a new rating gets added, the properties on the object being rated get set. Just like the create method, the behavior needs to work even for users without the permissions needed to change the object's properties. First update the addRating()(Rating.java) method:
total = total + rating;
count = count + 1;
average = total / new Double(count);
setParentProperties(parentRef, average, total, count);
return;
18. Then, implement the setParentProperties() method by wrapping the old property setters with the AuthenticationUtil.runAs method:
protected void setParentProperties(final NodeRef parentRef, final
Double average, final int total, final int count) {
AuthenticationUtil.runAs(new RunAsWork() {
@SuppressWarnings("synthetic-access")
public String doWork() throws Exception {
// store the average on the parent node
nodeService.setProperty(parentRef, SomeCoModel.
PROP_AVERAGE_RATING, average);
nodeService.setProperty(parentRef, SomeCoModel.
PROP_TOTAL_RATING, total);
nodeService.setProperty(parentRef, SomeCoModel.
PROP_RATING_COUNT, count);
if (logger.isDebugEnabled()) logger.debug("
Property set");
return "";
}
},
"admin");
}
19. Now you need to let the web script framework know that this new class is the controller for the rating web script. Create a new Spring bean configuration file in |config|alfresco|extension called someco-scripts-context.xml with the following content:
springframework.org/dtd/spring-beans.dtd'>
20. Deploy the new web script.
Once you get the UI widget wired in, it will be easier to test. For now, go to the Web Script home page and refresh the list of web scripts. Verify that your new web script shows up. To navigate to the index for the new web script directly, go to this URL:
You should see:
Post Content Rating
POST /alfresco/service/someco/rating
POST /alfresco/service/someco/rating.json
POST /alfresco/service/someco/rating.html
Description: Sets rating data for the specified node
Authentication: guest
Transaction: none
Format Style: extension
Default Format: json
Id: com/someco/ratings/rating.post
Description: classpath:alfresco/extension/templates/webscripts/com/someco/ratings/rating.post.desc.xml )







No comments:

Post a Comment