Can I add multiple servlets to a WebAppContext? - scala

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.

Related

Apache Sling Resource Mapping in CQ 5.6.1

I've been taking several hours fiddling this Resource Mapping for no luck. I have put a new node in /etc/map/http named GoogleAnalyticsMap. It had the following properties:
Name: jcr:primaryType
Type: Name
Value: sling:Mapping
Name: sling:internalRedirect
Type: String
Value: /content/dam/website/Common/my_google_analytics_key.html
Name: sling:match
Type: String
Value: [^/]+/[^/]+/my_google_analytics_key.html
Funnily, when i checked to /system/console/jcrresolver or Adobe CQ Web Console Sling Resource Resolver. It resolves into the following
Pattern: ^http/[^/]+/[^/]+/my_google_analytics_key.html
Replacement: /content/dam/website/Common/my_google_analytics_key.html
Redirect: internal
I have no idea how they could register ^[^/]+/[^/]+/welcome$ as shown in the example and did not have the 'http' there. Nevertheless, whenever i try to hit the pattern locally (i.e. http://localhost:4502/my_google_analytics_key.html) it only shows resource not found. Also checked through the Configuration test section that available in Adobe CQ Web Console Sling Resource Resolver it says that it can't resolve. Did i miss something?
, type=sling:nonexisting, path=/my_google_analytics_key.html, resource=[NonExistingResource, path=/my_google_analytics_key.html]
Thank you for the help.
p.s. i've checked the Sling documentation also, however, it baffles me that i can't add sling:alias, perhaps its also something to do with the sling version. Nevertheless, i should ask this as second question later, once the sling:match is working properly.
Edit: fiddling a bit, changing the sling:match to localhost.4502/google.html does let it to redirect localhost:4502/google.html to the desired DAM item. Well, i'm still asking for 'domain-free' matching though.. so i have no trouble when using the mapping for all environment i have..
Edit, Updates:
Apparently due to me put the new sling:Mapping under http folder it will always prefix the path with http. Perhaps the example is meant to be put not under http folder.
Next item is, it will always assume the matching item will be protocols, domain, and port separated by dots (yes, even \. is not a valid input and CQ or rather sling will sanitize it somehow). Something like *.(4502|4503|80|443)/my_google_analytics_key.html will accept any domains and those designated ports. I do wonder if it really the case, since they says regex but it does not feel so much regex.
Some says that sling:internalRedirect should be a String[] - yes i know the docs says String. I have not test this further and take it as it is..

AEM resource resolver failing

I am working on the AEM resource resolver and I currently have the following configuration on the Adobe Sling Resource Resolver Factory.
/content/mywebsite/>/
I have this a tag being generated from a component that looks something like:
<a data-desktop='/content/mywebsite/desktop.html'
data-android-href='/content/mywebsite/android.html'
data-ios-href='/content/mywebsite/mywebsite/ios.html'
href='/content/mywebsite/normal.html'>Click here</a>
This should have ideally been resolved to something likeL
<a data-desktop='/desktop.html'
data-adroid-href='/android.html'
data-ios-href='ios.html'
href='/normal.html'>Click here</a>
The irony is the last href in the above a tag is also not resolved by the resource resolver and I'm still getting the unresolved URL on dispatcher.
All the other resource resolver for a tags with just <a href='/content/mywebsite/something.html></a>' gets resolved. I don't understand why the resource resolver does not pick up the one with multiple data elements.
Are you sure it depends on the number of attributes? It looks like your configuration only affects resource resolution and not the outgoing mapping. The rule will be applied for incoming requests so when the user hits your AEM instance with /something.html, the Resource Resolver will look for the resource at /content/mywebsite.something, as well as other paths mapped to the root (if any) but as far as I understand, it will not affect the way AEM renders links to that content.
Try changing your rule so that it uses a two way mapping: /content/mywebsite/:/
To quote the description of the URL Mappings field in the Apache Sling Resource Resolver Factory configuration in the OSGi console:
List of mappings to apply to paths. Incoming mappings are applied to request paths to map to resource paths, outgoing mappings are applied to map resource paths to paths used on subsequent requests. Form is <internalPathPrefix><op><externalPathPrefix> where <op> is ">" for incoming mappings, "<" for outgoing mappings and ":" for mappings applied in both directions. Mappings are applied in configuration order by comparing and replacing URL prefixes. Note: The use of "-" as the <op> value indicating a mapping in both directions is deprecated. (resource.resolver.mapping)
You can easily test the configurations you setin the Apache Sling Resource Resolver Factory using the Configuration Test field on the Resource Resolver page in the OSGi console. You'll find it at http://<host>:<port>/system/console/jcrresolver
Use the Resolve and Map buttons to se.e how the path is transformed both ways.
Also, if you're getting inconsistent behaviour between components, check if they both map the URLs using resourceResolver#map if not covered by the Externalizer already.

What is a REST response, what does it do?

I had made a REST webservice using redirecting to various paths like if i need to delete some user then i will redirect the user to this address in the #Path annotation :
user/delete
and therefore there is no thing like RESPONSE i have used.
While going through a code given to me by my senior i came accross these lines :
java.net.URI uri = uriInfo.getAbsolutePathBuilder().path(id).build();
Response.created(uri).build();
What are these lines doing, i have no idea.
Can someone explain me this w/o wiki links or any other 'Basic Rest Service' links.
Without any explicit details about the uriInfo object I can only speculate its type is the JAX-RS UriInfo class.
The first line can be broken down as below:
java.net.URI uri = uriInfo.getAbsolutePathBuilder().path(id).build();
The getAbsolutePathBuilder is documented http://jackson.codehaus.org/javadoc/jax-rs/1.0/javax/ws/rs/core/UriInfo.html#getAbsolutePathBuilder%28%29
java.net.URI uri = uriInfo.getAbsolutePathBuilder().path(id).build();
The method returns a UriBuilder object. On which the 'path(...)' method is called passing the id so if the absolute path returned http://www.host.com (this may or may not have a port number) adding the id in this method will then result in the effectively Builder holding the two parts. The base URI and the path. The two values have not yet been put together
The build method then concatenates the two values resulting a full URI. For example http://www.google.com/id (Where http://www.google.com is the absolute path)
The second line
Response.created(uri).build();
Is basically saying 'Respond with a created (201) response code, and set a Location header containing the build uri value'

Redirect from Portlets

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.

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);