How to access Endeca keyword redirect results in the JSP layer with ATG? - oracle

I'm working on a web application with Oracle ATG 10.1.2 and Endeca 3.1.1 (without Endeca Experience Manager), and am trying to get keyword redirect functionality to work.
Ultimately, what I'm trying to accomplish is to get access to the keyword redirect information returned from Endeca (if there was any) in my JSP layer, so I can redirect the user to the keyword redirect URL, and/or display that URL as part of the rendered page.
To get results from Endeca, we are using the /services/guidedsearch packaged service (as described in on p51 of the Assembler Application Developer's Guide (v3.1.1).
If I use my browser to directly access the raw Guided Search output from the Endeca MDEX server, I can see my guided search entry and URL in the endeca:redirect property in the returned XML. I can also see the guided search entry with no problem in the Endeca JSP Reference Application ("orange app").
However, when I use the ATG InvokeAssembler droplet to get results from Endeca, the endeca:redirect entry doesn't seem to be included in the response. The ContentItem map that gets returned only has the following keys:
#type, name, navigation, breadcrumbs, resultsList, searchAdjustments, zones, endeca:siteRootPath, endeca:contentPath
There's no endeca:redirect key like I can see in the raw /services/guidedsearch XML output.
Here's the relevant snippet of my JSP code:
<dsp:droplet name="/atg/endeca/assembler/droplet/InvokeAssembler">
<dsp:param name="includePath" value="/services/guidedsearch" />
<dsp:oparam name="output">
<dsp:getvalueof param="contentItem" var="contentItem" vartype="com.endeca.infront.assembler.ContentItem" />
</dsp:oparam>
</dsp:droplet>
How can I access the keyword redirect information returned from Endeca?

You could also develop your own RedirectAwareHandler and simply extract the redirect from the SupplementList.
public ContentItem process(ContentItem pContentItem) throws CartridgeHandlerException {
ENEQueryResults executeMdexRequest = executeMdexRequest(mMdexRequest);
Object redirectURL = null;
if (executeMdexRequest.getNavigation() != null && executeMdexRequest.getNavigation().getSupplements() != null){
SupplementList supplements = executeMdexRequest.getNavigation().getSupplements();
Supplement supplement = null;
for (Object object : supplements) {
if (object instanceof Supplement) {
supplement = (Supplement) object;
if (supplement.getProperties() != null) {
redirectURL = supplement.getProperties().get("DGraph.KeywordRedirectUrl");
if (redirectURL != null) {
break;
}
}
}
}
}
//And now do your redirect
}

According to Oracle Support doc 1530390.1, the problem is that in ATG 10.1.2, the InvokeAssembler droplet is internally coded to use an Endeca ContentInclude object (which doesn't support keyword redirects), instead of using RedirectAwareContentIncludeHandler (which does).
Per that knowledge document, Hotfix p16099140 can be requested from Oracle Support to address this.

Related

How to change ContentURI in Weblogic Portlet?

I am developing an application which uses Weblogic portlets and Struts. All I need to do is to load different jsp's in the same portlet based on the web browser that client is using.
For eg: If I have a portlet called home.portlet. If the user is using IE it should display IE.jsp in the home.portlet, if he is using firefox I should display firefox.jsp in home.portlet.
This is what I have in home.portlet:
<netuix:content>
<netuix:jspContent contentUri="IE.jsp"/>
</netuix:content>
//in struts config file
<forward name="firefox" path="/firefox.jsp>
This is what I did to achieve it- In homeAction.java:
if(firefox)
return mapping.findForward("firefox");
So even if the user is using firefox it is displaying IE.jsp.
How can we change the jsp content in the portlet from the Struts Action Class so that I can check the kind of the browser the user is using and display the page accordingly??
All help and suggestions appreciated.
Thanks,
-Sai
You will have to check for browser in your homeAction.java and do the forward based on that.
Try this to check browser version in your action.
public void checkBrowserType (HttpServletRequest req)
{
String s = req.getHeader("user-agent");
if (s == null)
return;
if (s.indexOf("MSIE") > -1)
System.out.println("using Internet Explorer");
else if (s.indexOf("Netscape") > -1)
System.out.println("using Netscape");
// etc ...
}
My portlets wern't configured for struts. I changed that now, and its working fine.
EG:
<netuix:strutsContent action="getStudentList" module = "people/students"
refreshAction = "getStudentList" reqestAttrpersistence="none"/>
And then in the action class I am checking for the browser and displaying the appropriate jsp

Richfaces error page redirection with gatein, jboss 5.1.0 ga portlet bridge jars and my mistakes

i know there are a lot of similar questions out there about the same/similar topics but i could not apply any of the solutions to my problem.
I want to redirect user to a custom error page whenever an exception caught while rendering the portlet page.
why exception thrown while rendering the page ? Its because in the background we throw it to give user some useful information, designed that way and not going to be changed anytime soon, so my intention is to keep it that way.
I belive it would be better if i give examples:
This is simple portlet that i provide use name and press ">>" button to get some information about that user, in the previous implementation its working fine see the second picture..
Second picture:
as you can see layout is correct""(this is how it looked) the error
page has simply replaced the portlet content with its own content and
the error message that why we could not get any information about the
user. So far so good.
Now lets look at the problem case: We have upgraded from jboss 4.2.3 ga to 5.1.0 ga and now GateIn comes into play ground. Also there were old jars used to create this view of portlets, now they are all upgraded to newer ones.
Such as:
(org.richfaces.framework) Richfaces-api 3.3.3-final,
(org.richfaces.framework) Richfaces-impl 3.3.3-final,
(org.richfaces.framework) Richfaces-ui 3.3.3-final,
(com.sun.faces) jsf-api 2.2.14,
(com.sun.faces) jsf-impl 2.2.14,
(javax-servlet) servlet-api 2.5,
(javax-servlet) jstl 1.2
Gatein version: 3.4
and gatein itself uses jsr168 compatible jars + we have jsf 1.2 version (tags are used in this version).
Problem case:
as you can see the the portlet we want to get some user information is broken and merged into domain detailed portlet. which looks like a soup.
The code that generates this mess is also belongs to us. which was working correctly once, however its now somehow destroying the whole layout.
Let me show you the code that is rendering the views:
public void renderView(FacesContext context, UIViewRoot viewToRender) throws java.io.IOException, javax.faces.FacesException{
try {
super.renderView(context, viewToRender);
}catch(FacesException e){
Application application = context.getApplication();
ViewHandler viewhandler = application.getViewHandler();
PortletRequest request = (PortletRequest)context.getExternalContext().getRequest();
PortletConfig config = (PortletConfig)request.getAttribute(PortletConstants.PORTLET_CONFIG);
String errorView = config.getInitParameter(PortletConstants.PORTLET_FACES_ERROR_VIEW);
if(errorView == null || errorView.matches("")){
errorView = ProvPortletViewHandler.DEFAULT_FACES_ERROR_VIEW;
}
Throwable cause = e.getCause();
FacesMessage fm= findProvisioningException(cause);
if(fm == null)
{
request.setAttribute("ErrorMessage", "Unknown Error occured");
}
else
{
request.setAttribute("ErrorMessage", fm.getSummary());
}
viewToRender = viewhandler.createView(context,errorView);
context.setViewRoot(viewToRender);
viewhandler.renderView(context, viewToRender);
PortletSession objSes = (PortletSession)context.getExternalContext().getSession(false);
objSes.invalidate();
}
}
In this piece of code, you can see that there is super.renderView(context, viewToRender);
It goes all the way to the services and makes the service call. service calls returns an exception that this user has not information in DB. and this exception is converted into FacesException on the road (we are doing it).
The problem is not the exception its nor converting it to a FacesException.
The problem occurs in this part
viewToRender = viewhandler.createView(context,errorView);
context.setViewRoot(viewToRender);
viewhandler.renderView(context, viewToRender);
as far as we debugged. We belive somehow the old view which was partially rendered due to exception cannot be replaced with the error view.
But what could do that if it was working previously. we have not changed this part of the code.
Is this information enough to throw an idea about the problem ?
Would you guys need for more details ?
What do you think we are doing wrong here?
Thanks & regards
After looking deep, it is seen that when the request comes, its response is created and filled at this point. It has already HTML content inside. When trying to redirect new jsp file, it appends new HTML elements to the that response. Thus HTML elements inside response become obscure to Gate-in.
In order to avoid this problem, resetting response is enough. It can be done resetting the response buffer, can be seen on the code;
viewToRender = viewhandler.createView(context, errorView);
context.setViewRoot(viewToRender);
**((javax.portlet.RenderResponse) context.getExternalContext().getResponse()).resetBuffer();**
viewhandler.renderView(context, viewToRender);

How to build Seo Urls in WebSphere Commerce inside Java in Websphere Commerce 7

Is there an easy way to build seo friendly urls inside a Java class within WebSphere Commerce 7 (Feature Pack 6).
In JSP files you can use the provided tag, but is there also an easy way to build the seo urls inside a Java method.
I rebuild the tag methods in an own helper class but this seems to be a little over the top and can contain a lot of errors.
Does IBM provide helper classes which I havenĀ“t found yet?
Thanks
To create SEO URLs you can use the SEOURLMapper.
Example:
String patternName = "CanonicalItemURL";
TypedProperty properties = new TypedProperty();
properties.put("storeId", storeId);
properties.put("langId", languageId);
properties.put("catalogId", catalogId);
SEOURLMapper mapperInstance = SEOConfigurationRegistry.singleton().getMapperInstance();
String seoUrl = mapperInstance.constructDynamicURLByPatternName(patternName, properties, null);
Actually all these SEO URLs are created by a JAVA class only (internally). You need to check your wc-server.xml where you define the SEOConfiguration.
There must be a URLMapper class associated with the configuration. By default it's SEOURLMapper. Check its methods constructSEOURL and deconstructSEOURL.
TypedProperty urlProperties = new TypedProperty();
urlProperties.put("storeId", storeId);
urlProperties.put("catalogId", catalogId);
urlProperties.put("langId", languageId);
urlProperties.put("urlLangId", languageId);
urlProperties.put("productId", productId);
SEOURLMapper mapper = SEOConfigurationRegistry.singleton().getMapperInstance();
url = mapper.constructSEOURLByPatternName("ProductURL", urlProperties, null, null, null);
The above code would help you in generating Product URL for language ID -> languageId.
We have to pass urlLangId, if we need to have the URL in multiple languages or else it would be always pick up EN urlkeyword.
FYI - ProductURL is the pattern name in patterns XML file.

I want my Domino Servlet to get an authenticated user session

It seems a like a pretty fundamental question, in a running Servlet hosted on Domino I want to access Domino resources that I have wisely protected using the the very fine security of IBM Notes and Domino.
I want the Servlet to be able to read and write data to Domino whilst keeping that data from the client that called the Servlet (or xAgent) and preventing the client from writing directly.
I'd be happy to be able to get a session that represented the signer of the application. I can get a session for a registered user by calling the Servlet using ?open&login and signing in. That's not practical.
I've looked here: How can you use SessionAsSigner in a Java Bean called from an XPage? where Mark Leusink (https://stackoverflow.com/users/1177870/mark-leusink) implies the use of ExtLib's getCurrentSessionAsSigner() could be used. I've tried it, having signed the whole application with a single user id and it doesn't return a session. The answer seems to lie in the Servlet's inability to get a FacesContext object.
This feels like the answer should be obvious but it isn't to me. Any ideas?
FacesContext is JSF stuff and can be used from XAgent (=XPage).
In a servlet you can do this:
Session session = NotesFactory.createSession(null, "user", "password");
Server ID usually has no password and doing this will use the server ID:
Session session = NotesFactory.createSession();
Check the source of the WebDav project on OpenNTF. It has all the code you need
There have been lots of good answers to the original question. Thanks very much.
The solution I propose to use is to port the code I have to OSGi plugins. It appears that java code/Servlets within the NSF context are subject to security controls that are relaxed when the same code runs within the OSGi context. The code:
try {
NotesThread.sinitThread();
Session s = NotesFactory.createSession("","<my username>","<my password>");
.....
session = null;
} catch (Exception e) {
} finally {
NotesThread.stermThread();
}
Runs fine in the OSGI context, but within in an NSF produc
com.ibm.domino.osgi.core.context.ContextInfo.getUserSession()
Jason - I assume you basically want the same functionality you would get running a Web Query Save agent if you didn't select run as Web User selected, in other words as the signer of the code.
You could try setting up a internet site rule to allow basic authentication for the specific application path you wanted to use - might be worth using a subdomain for this.
Then within the Servlet call this URL, whilst setting the Basic authorization parameters (username & password).
Something like this.
URL url = new URL(URL_TO_CALL);
String authStr = "USERNAME:PASSWORD";
String authEncoded = Base64.encodeBytes(authStr.getBytes());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setRequestProperty("Authorization", "Basic " + authEncoded);
InputStream is = connection.getInputStream();

How do I get rid of the ? (question mark) in the URL that identifies the start of the query string?

I am using ColdFusion 9.1.2.
I set up a new web site that parses the query string after the domain name and slash. What is left is the MusicianID and then a string used to help with SEO. The URL looks like this:
http://awesomealbums.info/?1085/jim-croce
http://awesomealbums.info/?1077/james-taylor
When I share it using Facebook, Facebook removes the question mark and encodes it. They can't seem to parse it so they display it as the home page.
These throw an error that I can't control:
http://awesomealbums.info/1085/jim-croce
http://awesomealbums.info/1077/james-taylor
I notice that StackOverlfow and other sites are able to exclude the question mark that starts a query string. I would like to do the same. I, however, can't change any IIS or CF Administrator settings. I need to code the solution. I've tried, but I get IIS telling me they can't find the page.
I want my URLs to look like this:
http://awesomealbums.info/1085/jim-croce // same as above but no ?
http://awesomealbums.info/1077/james-taylor // same as above but no ?
Here's the code that I am using right now to parse the URL and get the MusicianID.
<cfscript>
QString = CGI.QUERY_STRING;
if (QString eq "") {
include "Home.cfm";
} else if (QString eq "WhoAmI") {
include "WhoAmI.cfm";
} else {
IndexOfSlash = Find("/", QString);
if (IndexOfSlash eq 5) {
ThisID = left(QString, 4);
if (isNumeric(ThisID)) {
MusicianID = ThisID;
include "Musician.cfm";
}
} else {
location(url="http://www.awesomealbums.info" addtoken="false");
}
}
How can I alter my site so that the question mark can be removed and the web server doesn't get funky and I can parse out the query string?
The keyword you are looking for is URL rewriting. It has to happen on the web server, since you want to handle all requests in the top-level directory. If your web server is the Apache httpd, you can do it like this:
RewriteEngine on
RewriteRule ^/(\d{4})/([\w-]+)$ /?$1/$2 [L]
or
RewriteRule ^/(\d{4})/([\w-]+)$ /Musician.cfm?MusicianID=$1 [L]
Since you can't modify the web server (as Roland correctly suggests) there is one alternative - use URLs that look like this:
http://awesomealbums.info/index.cfm/1085/jim-croce
Structured this way, the webserver (IIS) will still pass control to your script. Then you can start having CF take over control of the processing. Your CGI.query_string will be empty, but your cgi.path_info variable will contain /1085/jim-croce. You can then start parsing that and handling it as needed.
The answer for IIS is basically the same as Roland mentions in his answer. You need to use URL Rewriting, that is the only way to accomplish what you are looking to do. This is because technically the URL that you want to request, does not exist as a real page or resource on the server, and you need to use URL Rewriting to intercept the page request, map it using regular expressions, then pass it to your application as the query string (page parameters) that you are expecting. So, if you are doing this on a hosted server, contact your host and see if they have something setup or installed on the server for doing URL Rewriting. Most any decent host certainly will.
If you are using IIS7, then info on using the built in URL Rewriting can be found at the link:
http://learn.iis.net/page.aspx/460/using-the-url-rewrite-module/
If you are using an older version of IIS, then you need to install an application on the server that will do this as previous versions of IIS do not have built in support for regular expression based rewriting that you would need to properly map your URLs to the correct parameters on your query string. For older versions of IIS, I've used Helicon IsapiRewrite which you can find at:
http://www.isapirewrite.com/
riding off of jfeasel's answer, you can use ColdCourse:
http://coldcourse.riaforge.org/

Resources