I have two portlets on my web page :
The first one is a web content portlet that allows picking up an article and displays it.
The other one is the portlet I'm working on (Struts MVC).
What I want to do in the second portlet is to get the article id used to display the web content in the first portlet.
Is it possible ?
Thank you!
You can do it using some Liferay specific APIs, though the approach is not perfect, but it'll work.
You can use Liferay APIs to get list of portlets currently available on page. Then you can figure out by portlet IDs which portlets are of type WebContentDisplay. Then you can read their preferences and there will be the ID of WebContent Article they display.
Note however that there can be cases when you have more then one WebContent Display portlet on page, or have none of them. You can either read list of portlets on the page on each render, or you can make a config page where you can display a select box for site admin to choose what WebContent Display Portlet instance should the value be taken from.
Let me show you the code for the first option, and second option if you'll need it I suppose you will deduce how to implement it from given code sample (mind the comments):
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.model.PortletConstants;
import com.liferay.portal.model.PortletPreferences;
import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.portlet.PortletPreferencesFactoryUtil;
import com.liferay.util.bridges.mvc.MVCPortlet;
import java.io.IOException;
import java.util.List;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
/**
* Portlet implementation class WCDPrefReaderPortlet
*/
public class WCDPrefReaderPortlet extends MVCPortlet {
public void doView(RenderRequest request, RenderResponse response)
throws IOException, PortletException {
// Obtain Liferay's ThemeDisplay object (typical operation in Liferay)
ThemeDisplay themeDisplay = (ThemeDisplay) request
.getAttribute(WebKeys.THEME_DISPLAY);
// Get ID of current page
long plid = themeDisplay.getPlid();
try {
// Obtain portlets on current page as list of
// com.liferay.portal.model.PortletPreferences
List<PortletPreferences> pagePortlets = PortletPreferencesLocalServiceUtil
.getPortletPreferencesByPlid(plid);
for (PortletPreferences portlet : pagePortlets) {
// Portlet ID
String portletId = portlet.getPortletId();
// WebContent Display portlet has ID 56. Also it's instanceable,
// so we expect instance ID to be present, i.e.
// 56_INSTANCE_NWWDuJPL64xa
// 56_INSTANCE_N1m7pQGwcScG
// would be IDs of WebContent Display portlet
// PortletConstants.getRootPortletId(portletId) will return
// portlet ID part without instance ID. I.e. we expect just "56"
if ("56".equals(PortletConstants.getRootPortletId(portletId))) {
// If we would have portlet ID stored, we could load it's
// preferences using this code:
// PortletPreferencesLocalServiceUtil.getPortletPreferences(plid,
// portletId);
// Not needed for now, since we already have the
// corresponding
// com.liferay.portal.model.PortletPreferences object
// Here we get portlet preferences as XML -
// Liferay stores them that way
String prefsAsXml = portlet.getPreferences();
// Parsing XML and creating Portlet API PortletPreferences
// object
javax.portlet.PortletPreferences prefs = PortletPreferencesFactoryUtil
.fromDefaultXML(prefsAsXml);
// Read preference named "articleId" - WebContent Display
// Portlet uses this preference to store articleId
String articleId = prefs.getValue("articleId", null);
// Do something with the articleId value
System.out.println(articleId);
}
}
} catch (SystemException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.doView(request, response);
}
}
Yes, you can share data between two different portlets by setting it in session. Set the article ID by editing the portlet code (of 1st portlet), set it in the session and retrieve it in you portlet.
For setting and getting values (Inter portlet communication) example-->Check this
Related
I am developing JSF but the problem is in the java I believe. Ok so I have a table with requests, when I press the id of the request that is sent to the reviewRequest page with:
<h:inputHidden id="id" value="#{requestClass.requestID}" />
Now that's working because I load the request details on next page (by taking ID and retrieving object from database). now when I modify the object from reviewRequest and accept, it says it is stored successfully. I then view the same page again from table I click the request id and there it goes bang nullpointerexception. When it is loading the object this time, it pass the id to retrieve method then it only returns the change but not the whole object details like name, contacts, etc. only that the user of type x submitted modification y. retrieve method from DB works for sure because all over the app it is working correctly. Any idea? some of the code below for illustration:
public void callIsValidUser(){
boolean holder = isValidUser();
if(holder == true){
rsvIns = loadDetails();
}else{
try{
FacesContext.getCurrentInstance().getExternalContext().dispatch("pending.xhtml");
}catch(IOException ioe){
System.err.print(ioe);
}
}
}
the method above works the first time but not after modification. in isValid():
public boolean isValidUser(){
boolean valid = false;
try{
rsvLocal = oracleRsv.retrieveReservation(id);
String reqDivHead = rsvLocal.rdhUser.getUserID();
//rsvLocal.rdhUser.getUserResponse();
String supervisor = rsvLocal.sUser.getUserID();
String divHead = rsvLocal.dhUser.getUserID();
String currentUser = System.getProperty("user.name");
.....
now when I inspect the rsvLocal in netbeans debug mode, i see that rdhUser.response holds the modification I entered but all rest is null. How can this happen? how can some data be retrieved from object?
Thanks,
Most likely you did not load the data at the very beginning. Then JSF created an empty bean and sets the values from the form. Now everything not mentioned in the form (and of course every empty field of the form) contains null. This half-baked bean is now stored in the DB overwriting the complete row. If you now load the row again you will see what you call "my modifications" but what is the complete content of the DB. Your old data is lost.
The key point is: JSF and the DB-Layers do not deal with "modifications" of individual fields - they handle complete entities.
I am creatin an app in Java that checks if a webpage has been updated.
However some webpages dont have a "last Modified" header.
I even tried checking for a change in content length but this method is not reliable as sometimes the content length changes without any modification in the webpage giving a false alarm.
I really need some help here as i am not able to think of a single foolproof method.
Any ideas???
If you connect the whole time to the webpage like this code it can help:
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
public class main {
String updatecheck = "";
public static void main(String args[]) throws Exception {
//Constantly trying to load page
while (true) {
try {
System.out.println("Loading page...");
// connecting to a website with Jsoup
Document doc = Jsoup.connect("URL").userAgent("CHROME").get();
// Selecting a part of this website with Jsoup
String pick = doc.select("div.selection").get(0);
// printing out when selected part is updated.
if (updatecheck != pick){
updatecheck = pick;
System.out.println("Page is changed.");
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("Exception occured.... going to retry... \n");
}
}
}
}
How to get notified after a webpage changes instead of refreshing?
Probably the most reliable option would be to store a hash of the page contet.
If you are saying that content-length changes then probably the webpages your are trying to check are dynamically generated and or not whatsoever a static in nature. If that is the case then even if you check the 'last-Modified' header it won't reflect the changes in content in most cases anyway.
I guess the only solution would be a page specific solution working only for a specific page, one page you could parse and look for content changes in some parts of this page, another page you could check by last modified header and some other pages you would have to check using the content length, in my opinion there is no way to do it in a unified mode for all pages on the internet. Another option would be to talk with people developing the pages you are checking for some markers which will help you determine if the page changed or not but that of course depends on your specific use case and what you are doing with it.
I am having a hard time looking for an answer to my question. I am trying to create a folder/space in Alfresco. But I don't have any idea doing it? Can someone help me with this? I'm using Java webscript.
All I am at is this:
package org.alfresco.module.demoscripts;
import java.io.IOException;
import org.alfresco.web.scripts.AbstractWebScript;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptResponse;
import org.json.JSONException;
import org.json.JSONObject;
public class SimpleWebScript extends AbstractWebScript
{
public void execute(WebScriptRequest req, WebScriptResponse res)
throws IOException
{
try
{
// build a json object
JSONObject obj = new JSONObject();
// put some data on it
obj.put("field1", "data1");
// build a JSON string and send it back
String jsonString = obj.toString();
res.getWriter().write(jsonString);
}
catch(JSONException e)
{
throw new WebScriptException("Unable to serialize JSON");
}
}
}
If you're new to both Java and Alfresco, you may well find that writing your WebScript in JavaScript is a better bet for you. It's normally easier to get started with. There are lots of examples too to help you.
If you do decide to stick with Java, the starting points in the Alfresco wiki for you are Java Backed WebScripts and the Java Foundation API. One of the Java webscript examples show you how to create nodes (you can use either the NodeService or the FileFolderService, depending on if you want full control or an easy way).
You might also want to look at some of the advice in the Alfresco Wiki and on the forums for how to structure your data, as creating lots of new nodes straight under Company Home may or may not be the best option for you.
As was pointed out, you may want to start by using JavaScript instead of Java. Also, I'm noticing that you are creating a new JSON object in your code, but I'm not sure why.
For example, using JavaScript, a web script that accepts the name of a folder to be created under company home might have a controller that would look like this:
function main() {
var folderName = args.folderName;
if (folderName != null && folderName != "") {
// continue
} else {
status.setCode(500);
status.setMessage("Missing folder name argument");
status.setRedirect(true);
return;
}
var createdFolder = companyhome.createFolder(folderName);
model.createdFolder = createdFolder;
}
main();
The code looks for an argument passed to it called folderName and then uses the built-in "companyhome" root scoped variable to create the new folder. It then passes the newly-created folder node to the model so that some data about the new node can be echoed back to the user.
The name of the JavaScript controller (shown above) is createFolder.post.js. I checked it in to the repository under Data Dictionary/Web Scripts/example. Along with that, I checked in a file called createFolder.post.desc.xml, which is the web script descriptor:
<webscript>
<shortname>Create folder example</shortname>
<description>
<![CDATA[
Creates a new folder in Company Home using the name specified in the folderName argument.
]]>
</description>
<url>/example/createFolder?folderName={folderName}</url>
<format default="html">argument</format>
<authentication>user</authentication>
<transaction>required</transaction>
<family>Example</family>
</webscript>
And a file called createFolder.post.html.ftl, which is the HTML version of the web script view:
<html>
<head>
<title>Create folder web script</title>
</head>
<body>
Successfully created a folder with the following metadata:<br />
Name: ${createdFolder.name}<br />
ID: ${createdFolder.id}<br />
Noderef: ${createdFolder.nodeRef}<br />
</body>
</html>
Once checked in, I refreshed the web script index by going to http://localhost:8080/alfresco/s/index and clicking the "refresh web scripts" button.
I then invoked the web script using CuRL, like this:
curl -uadmin:admin -X POST "http://localhost:8080/alfresco/s/example/createFolder?folderName=foobar"
You'll notice that I chose to make my web script accept POSTs. If you wanted to use a different HTTP method, you'd simply change the file names accordingly.
Jeff
I would like to create Vanity URLs for web application built ontop of Playframework.
I have tried to add a parameter for index method in main page Application, this will work if i call http://localhost:9000/?vanity_url and not for http://localhost:9000/vanity_url.
How would i achieve this? I would like users to create their own urls for the solution has to be dynamic, just like on Facebook
In the route you would put
GET /{<[a-z]+>fanPage}/? Page.showFanPage
With this one you could obtain:
http://localhost:9000/facebook
I also recommend using the slugify method provided by play framework, usually you would both check if the slug exists in the database, and look up for slug to grab the data (title of the fanpage/who's the owner of the fan page/how many views/etc etc)
In the tables:
Name: fanpage
pageID integer or bigint
title varchar
slug varchar unique
owner integer
content text
In code:
public static void showFanPage(String fanPage) {
// use models to look for the slug
// grab the data
// do what you need to do
}
I'm going on examples here on how to create the urls since I don't know what app you are building:
GET /post/slug/? Page.createPage
POST /post/slug/? Page.processPage
public static void createPage() {
// remember to create the template
render();
}
public static void processPage(String slugName) {
// slugName refers to the input field
// check if the slug exists and throw error if it does
// process
}
(note this is just an example, I don't know what kind of application you are building)
I hope this helps, let me know if this is what you meant
I am creating a web application using EJBs and servlets. I have a page which displays a list of all items in the database. I would like to provide an option for the user to click on one of these items and this opens the SHOW servlet which gathers info regarding the item onto the page. I do not want to create a page for every single item. Instead I would like to create ONE SHOW servlet which can be used for all items. I am not sure how to provide this option through clicking on the name of an item, and also how to send the parameters...since it depends on what item the user chose.
Can someone help me please?
Thank you
When you generate the product listing, you can just make the IDs of all the database items parameters in the link.
Product Foo
Then in the doGet() method of your ShowProduct servlet, you can call the HttpServletRequest.getParameterValues() method to get that parameter's values and do the lookup in your database.
e.g.
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String[] params = request.getParameterValues("productID");
String productID = params[0];
...
}
Pass the unique ID of the item into the SHOW servlet. Then get that item's data from the DB and create your new page with that data.
Try having the show link point to your show servlet like this:
"/ShowServlet?itemID="+itemID