Redirect from Portlets - portlet

I have this:
I try to redirect from portlet Historial to portlet Reclamos i'm doing this:
String pageUnique= "prueba.page.SRSC.Reclamos" ;
String portletUnique= "prueba.portlet.SRSC.IngresoSolicitudReclamos" ;
#SuppressWarnings("rawtypes")
String targetURLStra = ServletURLHelper.generateUrl(pageUnique,portletUnique, (HashMap) customerContext, app.getHttpServletRequest(), app.getHttpServletResponse());
I put this in one method and call into the button; that suppose redirect to the Portlet Reclamos...
But i get this error:
[5/15/13 11:20:39:322 PET] 00000068 servlet [PA_SRSCPORTAL_1] [/wps/PA_SRSCPORTAL_1] [/genjsp/prueba/portlets/portletHistorial_pgError.jsp]: Initialization successful
I have each portlet in different war and the portlet Historial is in IBM Portlet Factory and the portlet Reclamos is in JSR 168
Please any help

You cannot redirect from "a portlet" to "another portlet". If they are in different WARs, you cannot even use the same JSPs to implement the UI (at runtime). If you literally want to use "the same" jsp, I suppose that you can add this to your deployment environment and copy them in your buildscripts, but it feels clunky and not optimal.
Keep in mind that each WAR file is located in a different classloader and well isolated from each other. One JSP file could not access the variables (attributes, classes, it's hard to even use proper terminology here) injected by another webapplication/WAR.

Related

Spring WS remove flexible URL, Restricting WSDL URL and service URL

I'm trying to make a Spring Boot Soap WebService application, and was following the Get Started (https://spring.io/guides/gs/producing-web-service/) example to learn how to do this.
I've created what I want, but I have two URL problems with this setup and I could not find what configuration should I change to fix this :
WSDL URL basic is localhost:8080/ws/countries.wsdl but anything like localhost:8080/ws/whatever/countries.wsdl is correct
service URL for SoapUI request is localhost:8080/ws but anything like localhost:8080/ws/whatever is correct
I know that this is a feature for Spring WS, but I want a fixed URL (without 'whatever' in both cases) and could not find what to change for this
There is no straight forward way to restrict the way you want.
SOAP service is not URL based.
SOAP message body describe the endpoint.
The thing you wanted is possible following way.
Changing URL mapping in ServletRegistrationBean to restrict URL access
Existing /ws/* mapping is the reason why all the /ws/whatever url successfully responded.
Change as new ServletRegistrationBean(servlet, "/ws");
Effect will be you can not request other than /ws URL
Now the problem is, you can not get WSDL by this mapping.
Solution to get WSDL
The DefaultWsdl11Definition is actually generating WSDL from XSD on every request.
Save countries.wsdl to resource folder as static WSDL file.
Remove DefaultWsdl11Definition bean.
Create a new SimpleWsdl11Definition bean as like
#Bean(name = "countries")
public SimpleWsdl11Definition orders() {
SimpleWsdl11Definition wsdl11Definition = new SimpleWsdl11Definition();
wsdl11Definition.setWsdl(new ClassPathResource("countries.wsdl"));
return wsdl11Definition;
}
Now add another static URL mapping in ServletRegistrationBean. As it will be finally look like new ServletRegistrationBean(servlet, "/ws", "/ws/countries.wsdl");
This practice is good for development phase as you can publish easily the changed definition. But it is recommended to use static-wsdl for production environment. Details ** here
Just change
return new ServletRegistrationBean(servlet, "/ws/*");
for example to
return new ServletRegistrationBean(servlet, new String[]{
"/ws/v1/countries.wsdl",
"/ws/v2/countries.wsdl"
});

What is ATG pipelines and how does it works?

I have some idea on atg droplets, dsp tags and writing custom droplets. I would like to know about pipelines on ATG topics. When I trying to refer oracle documentation for this I'm getting bit confused with understanding what it is and working flow of it. Can I create one custom pipeline manager which executes my custom processors sequentially.If possible how can I do this?? How to trigger my pipeline manager from my jsp page. Please guide me some tutorials or online documents for best learning for pipelines.
Code snippets is highly preferable.
Thanks in advance
A pipeline is an execution mechanism that allows for modular code execution. Oracle ATG Web Commerce uses pipelines to execute tasks such as loading, saving, and checking out Orders .The PipelineManager implements the pipeline execution mechanism.
There are two request-handling pipelines used by Dynamo.
• DAF Servlet Pipeline - It is used to handle the JSP request.
• DAS Servlet pipeline - It is used to handle JHTML request. Because JHTML is a proprietary language, it relies on the page compiler provided in the DAS servlet pipeline to generate JHTML into a servlet that’s rendered as HTML by the application server.
And also there is something called commercePipeline which takes care of order processing.
Request-Handling pipelines and commerce pipelines works in different ways.
DAS/DAF(ie., request pipelines)
It's a configuration defined with a series of servlets executed in a sequence on basis of each servlet's output. One of Dynamo's most important tasks is handling HTTP requests. In handling these requests, Dynamo uses session tracking, page compilation, Java Server Pages, and other powerful extensions to the basic Web server model.Request handling can usually be broken down into a series of independent steps. Each step may depend on additional information being available about the request, so order does matter. However, the individual steps are separable. For example, a typical request might go through these steps:
1) Compare the request URI against a list of restricted directories, to make sure that the user has permission to access the specified directory.
2) Translate the request URI into a real file name, taking "index" files into account when the file name refers to a directory.
3) Given the file name's extension, determine the MIME type of the file.
4) From the MIME type, dispatch the request to the appropriate handler.
So DAF/DAS pipelines comes into picture when there is a request. In atg_bootstrap.war web.xml has the information about the server startup.
When the server starts NucleusServlet.java gets loaded in the app server. This class initializes nucleus and other components and then adds all of them to nucleus namespace. And when a web application is accessed (DynAdmin,CRS,MotopriseJSP), nucleus routes the flow to either daf/das pipeline. If the application MIME type is Jhtml then das pipeline processes the request further. It is routed to DynamoProxyServlet class where it does the further processing by calling list of servlets. And if it is .jsp then Daf pipeline handles the further requests by calling PageFilter class.The reason for using a filter but not a servlet to invoke DAF pipeline is:
JSP pages and fragments are handled by the application server meaning that JBoss, WebLogic , WebSphere is the one responsible for compiling and executing the resulting page code. The best way to hook into this process is by using a Filter. For JHTML pages, that's a different story since the app server (not all app servers)can't parse and compile the pages. A servlet is used to redirect the request down the DAS pipeline where the page can parsed and executed by the ATG page compilationmechanism.
In case of Commerce Pipeline:
Pipeline Manager implements commerce pipeline functionality by reading a pipeline definition file ie., commercepipeline.xml. When application is deployed ,Nucleus initializes pricing engine, where OrderManager initializes pipelineManager. OrderManager.processOrder method invokes the pipeline chains in commercepipeline.xm. A pipeline chain would have processors which are simple java classes doing small operations .This xml can be extended by adding a custom processor. But in cases where a single processor need to be called, call runProcess method of pipelineManger by passing processorchaninId .
Extending DAF/DAS pipeline and commerce pipeline are not same
we can create our own custom servlets to put it in DAF/DAS pipeline .
extend you own servlet class wither with PipelineableServletImpl or InsertableServletImpl
and re-write the service method depending on what you want to do.Further details are widely available on the internet :)
and coming to commerce pipeline
Commerce pipeline is defined in an xml file located in /B2CCommerce/config/atg/commerce/commercepipeline.xml.PipeLine manager is responsible load the pipeline definition xml and initialize the pipeline chains. Write your processor class. Custom Processor class should be an implementation of PipelineProcessor.
extend your own class by PipelineProcessor and re-write runProcess method.You also have to create respective .properties file for your processor.And then in
B2CCommerce/config/atg/commerce/commercepipeline.xml
<pipelinechain name=" lastExistingchain" transaction="TX_REQUIRED" headlink=" lastExistinglink">
……..
<transition returnvalue="1" link=" sampleDemoLink"/>
</pipelinelink>
<pipelinelink name="sampleDemoLink" transaction="TX_REQUIRED">
<processor jndi="demo/atg/order/processor/MyProcessor"/>
</pipelinelink>
</pipelinechain>
restart ATG server.
Coming to you other question that if we can create our own pipeline manager
Answer is yes.
Just create /atg/registry/PipelineRegistry/ .properties file in your local config folder.PipelineRegistry is a service where all pipeline managers are registered
this service has property called pipelineManagers just append your pipeline manager component to this property.if you want to use existing commercePipelineManager class but with different bunch of processors executing one aftr the other.create a definition xml file which looks something like this
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE pipelinemanager
PUBLIC "-//Art Technology Group, Inc.//DTD Dynamo Pipeline Manager//EN"
'http://www.atg.com/dtds/pipelinemanager/pipelinemanager_1.0.dtd'>
<pipelinemanager>
<!-- This chain updates (saves) an Order to the repository -->
<pipelinechain name="updateOrder" transaction="TX_REQUIRED" headlink="updateOrderObject">
<pipelinelink name="updateOrderObject" transaction="TX_MANDATORY">
<processor jndi="/atg/commerce/order/processor/SaveOrderObject"/>
<transition returnvalue="1" link="updateCommerceItemObjects"/>
</pipelinelink>
<pipelinelink name="updateCommerceItemObjects" transaction="TX_MANDATORY">
<processor jndi="/atg/commerce/order/processor/SaveCommerceItemObjects"/>
<transition returnvalue="1" link="updateShippingGroupObjects"/>
</pipelinelink>
<pipelinelink name="updateShippingGroupObjects" transaction="TX_MANDATORY">
<processor jndi="/atg/commerce/order/processor/SaveShippingGroupObjects"/>
<transition returnvalue="1" link="updateHandlingInstructionObjects"/>
</pipelinelink>
<pipelinelink name="updateHandlingInstructionObjects" transaction="TX_MANDATORY">
.......
.......
<pipelinechain name="rejectQuote" transaction="TX_REQUIRED" headlink="quoteRejection">
<pipelinelink name="quoteRejection" transaction="TX_MANDATORY">
<processor jndi="/atg/commerce/order/processor/RejectQuote"/>
</pipelinelink>
</pipelinechain>
<!-- This pipeline chain should be called when a requested quote is to be completed -->
<pipelinechain name="completeQuote" transaction="TX_REQUIRED" headlink="completeQuoteRequest">
<pipelinelink name="completeQuoteRequest" transaction="TX_MANDATORY">
<!-- this is a dummy processor that should be extended to save quote details -->
<processor jndi="/atg/commerce/order/processor/CompleteQuoteRequest"/>
</pipelinelink>
</pipelinechain>
</pipelinemanager>
here you can mention your custom processors.
As you have registered your new pipelinemanager in pipeline registry.It gets automatically initialized.So if you do any operation in JSP related to your pipeline,in background all the processing gets done.
There are two entirely separate things in ATG commonly known as pipelines.
They are not at all related to one another.
1. The Servlet Pipeline
This is a chain of servlets through which all requests pass before hitting your custom code (JSP page, Form Handler, Droplet or anything else). The purpose of this pipeline is to decorate the incoming request to provide the request with the context that the ATG framework needs to, for example, associate the request to a Dynamo Session and to load a User Profile. The DAS module defines the basic servlet pipeline and various modules add additional servlets into it.
You modify this pipeline by changing the nextServlet or related properties of existing components, and by creating Nucleus components that are instances of classes extended from PipelineableServlet
You would choose to customise this if you wanted to perform an action or make a decision on each incoming request - somewhat similar to what you would use Filters in standard J2EE web applications or Interceptors in a Spring MVC application.
You can see what is defined in your servlet pipeline by looking the /atg/dynamo/servlet/dafpipeline/DynamoHandler component in the Dynamo Admin interface.
2. Processor Chains
A processor chain is a way of executing discreet processes and linking them together based on the outcome (resulting status code) of each process. There is a component in the Nucleus called the Pipeline Manager which holds the configuration of each Processor Chain defined in the system, and manages the execution of these chains.
Processor chains are used by the Commerce module to manage, for example, the creation of an order to ensure referential integrity between all the constituent parts. This is sometimes called The Commerce Pipeline.
Processor chains are conceptually more related to scenarios, and completely unrelated to the servlet pipeline.
You modify a processor chain by creating or editing the XML file that defines the chain. You create new processors by creating a Nucleus component from a class that implements the PipelineProcessor interface.
You can see which chains are defined by looking at the PipelineManager component in the Dynamo admin interface. There is also a graphical Pipeline Editor in the ACC.
You would modify an existing pipeline chain if you want to add or remove a step in it.
You would create a new chain if you wanted to split a long and complex process - usually repository operations - into multiple discrete steps to be sequenced together by an externalised process flow.

WCS7 best practice to receive certain catalog entry information?

[WCS 7, FixPack 7, Feature Pack 6]
I need to generate a feed with certain catalog entry (product) information such as name, image(s), category, price, seo-url, descriptive attributes and so on.
To generate this feed i will use the scheduler framework and created a controller command which will be invoked after a certain time has passed.
Now i need to receive the catalog entry data of each item in a specific store/catalog.
As far as i know there are several ways to achieve this:
Access Beans
SOA (new Access Profile with specific SQL)
I tried to use Access Beans to get all necessary information but I got stuck with seo-url, price etc.
Are there more ways and what is the best practice to get a specific set of catalog entry attributes?
I suggest you study/investigate in your WCS Development environment how site map generation schedule command is implemented (SitemapGenerateCmd) and how it is calling the JSP template file (sitemap.jsp)
you need to modify a bit in your command to create a jsp template for your feed and call that template from your scheduler command you've created .
calling template command for messaging system, make sure to use following properties in ActionForward tag to register the JSP for messaging from back-end:
example:
<forward className="com.ibm.commerce.struts.ECActionForward"
name="SitemapIndexView" path="/SitemapIndex.jsp">
<set-property property="direct" value="true"/>
<set-property property="resourceClassName" value="com.ibm.commerce.messaging.viewcommands.MessagingViewCommandImpl"/>
<set-property property="interfaceName" value="com.ibm.commerce.messaging.viewcommands.MessagingViewCommand"/>
<set-property property="properties" value="storeDir=no"/>
<set-property property="implClassName" value="com.ibm.commerce.messaging.viewcommands.MessagingViewCommandImpl"/>
</forward>
then the logic for extracting data from your product/catalog beans will be handled inside the JSP and you can easily form the output data as you want (XML, CSV, JSON .. etc)
the advantages and benefits of using this way are you can leverage Commerce Server OOTB JSTL tags , WCF tags for retrieving all information and using wcf:url for SEO URLS OOTB even you can call BOD/SOA commands using <wcf:getData tag and finally your will get more structured design that can easily maintain and reuse in future .
sitemap.jsp is a good resource for you how to iterate through catalog and sub-catalog to extract product info.
hope that those help you find your solution. need some search and understanding of existing sitemap generation utility .
Thanks.
Abed

Servlet: forward request to Servlet by its name when using annotations instead of web.xml?

I have an entry servlet (called DispatcherServlet) which redirects all incoming GET and POST requests at /* to other servlets depending on a configuration parameter. In order to dispatch the request to other servlets, I use their name instead of a path, because my DispatcherServlet would end up in an endless loop while listening to /*.
The "old" way was to give servlets a name in the web.xml descriptor:
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>mypackage.MyServlet</servlet-class>
</servlet>
Afterwards, one is able to address the servlet by its name, for example, when using a RequestDispatcher. The code in my DispatcherServlet looks like this:
RequestDispatcher dispatcher = getServletContext().getNamedDispatcher("MyServlet");
dispatcher.forward(request, response);
This works perfectly. But, I would like to use the "new" Servlet 3 annotations without the web.xml, hence I do this:
#WebServlet(name="MyServlet")
public class MyServlet extends HttpServlet {
...
But now, getServletContext().getNamedDispatcher("MyServlet") within my DispatcherServlet returns null instead of the appropriate dispatcher for MyServlet, although I expect that #WebServlet(name="MyServlet") behaves the same like <servlet-name>MyServlet</servlet-name>
I have tested this on Tomcat 7.
Is this because MyServlet has not been loaded yet by the time when DispatcherServlet is called and hence the name of MyServlet is not known? If so, what sense does the #WebServlet(name="...") annotation make ;)
Please don't answer with something like "why don't you use filters?" etc. This is more about the background of annotations vs. web.xml
Thanks in advance!
(ps. please change the title if you find a more suitable one ;))
If you do not specify the urlMapping with the name, you will need do add the full class name. Like
RequestDispatcher dispatcher = getServletContext().
getNamedDispatcher("mypackage.MyServlet");
It works for me if the servlet is annotated as:
#WebServlet(urlPatterns="/Servlet", name="Servlet")
or better:
#WebServlet(urlPatterns="/Servlet", displayName="Servlet", name="Servlet")
Also, you can try to get your servlet name with:
getServletName()
By just comment with #WebServlet is not enough to load a Servlet into the Web container; you must include at least one URL pattern, and if you don't want to expose the Servlet to keep it for internal forward only, set the URL to start with '/WEB-INF/'.
And keep in mind that the 'name' property is buggy, so not use it.
#WebServlet(urlPatterns = "/WEB-INF/thisServlet")
public class FooServlet extends HttpServlet {
...
}
and to forward the request, call something like this:
servletContext.getNamedDispatcher(FooServlet.class.getName()).forward(request, response);

Can I add multiple servlets to a WebAppContext?

I have the following Scala code to setup a Jetty server with Scalatra.
val server = new Server(8080)
val context = new WebAppContext()
context.setResourceBase("visualization")
context.addServlet(new ServletHolder(new CallTreeServlet(dataProvider)), "/*")
context.addServlet(new ServletHolder(new DataLoadingServlet(dataProvider)), "/*")
server.setHandler(context)
My problem is that it seems to work only if I register a single servlet.
If I register more than one, like I do in the code I posted, it loads only one of them.
Is it possible to load multiple servlets? I guess it is, but I can't figure out how.
If I try to load a page from the first servlet I got this error message that references only pages belonging to the second servlet:
Requesting "GET /callTrees" on servlet "" but only have:
GET /components
POST /load
POST /searchCallTrees
POST /selectPlugIn
To troubleshoot this, you should verify the servlet lifecycle. One convenient way to do this is to peruse the servlet container's logs to see what it reports while starting up the web application. It should tell you about each web app ( servlet context ) and each servlet . . .
However, I think I see what your problem is. Your servlet path mappings are kind of funky. It looks to me that you are mapping both servlets to receive ALL requests. This can't work, from a practical point of view, and might not work in terms of the servlet rules. From the servlet specification:
SRV.11.2
Specification of Mappings
In the Web application deployment descriptor, the following syntax is used to define
mappings:
• A string beginning with a ‘/’ character and ending with a ‘/*’ suffix is used
for path mapping.
• A string beginning with a ‘*.’ prefix is used as an extension mapping.
• A string containing only the ’/’ character indicates the "default" servlet of
the application. In this case the servlet path is the request URI minus the con-
text path and the path info is null.
• All other strings are used for exact matches only.
I suggest you make them both unique. As it looks now, you have them both at "/*" which is kind of like the "default servlet", but not . . .
Why not try "/first/" and "/second/" as a sanity check. Then move from there toward getting the configuration how you like.