Including a JSP into a sling servlet - osgi

I'm currently working on a small project, trying to help someone figure out how to wire up a component.
Ideally we'd like to do 2 things:
have a jsp that renders the template
have all our business login in a SlingAllMethodServlet
Gist of servlet definition:
package definition...
import statements...
#SuppressWarnings("serial")
#SlingServlet(
resourceTypes="path/to/my/component",
methods="GET",
extentions="HTML")
#Properties({
#Property(name="service.pid", value="<my service class>", propertyPrivate=false),
#Property(name="service.description",value="<description>", propertyPrivate=false),
#Property(name="service.vendor",value="<company>", propertyPrivate=false)
})
public class MyComponentServlet extends SlingAllMethodsServlet {
#Override
protected void doGet (SlingHttpServletRequest pRequest, SlingHttpServletResponse pResponse) throws ServletException, IOException {
...
}
#Override
protected void doPost(SlingHttpServletRequest pRequest, SlingHttpServletResponse pResponse) throws ServletException, IOException {
...
}
}
This actually works great, when I include the component on a page this runs. The problem (as you might expect) is that I'm consuming the HTML extension here. So "component.jsp" isn't getting picked up for render.
I'm curious if someone knows how to do one of the following:
Include the JSP for render in this servlet (i.e. i saw some interesting stuff on 6dimensions regarding pageContext#include and pageContext#pushBody: http://labs.sixdimensions.com/blog/2013-08-13/cq-resource-inclusion-servlet/)
Set up this servlet, so that this servlet runs at that path before the JSP is rendered.
Any insight would be great.
thank you,
brodie

Including scripts
Use following construction to include script /apps/test.jsp inside the servlet and pass some values (bindings) to it:
#Reference
private ServletResolver servletResolver;
public void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
Servlet servlet = servletResolver.resolveServlet(request.getResource(), "/apps/test.jsp");
request.setAttribute("sampleBinding", "bindingValue");
servlet.service(request, response);
}
The script itself may look like this:
<%#page session="false" contentType="text/html; charset=utf-8"
%><%#include file="/libs/foundation/global.jsp"%>
Binding value: ${sampleBinding}
Using models
You may also consider a second approach - don't create servlet for each component, but stick to JSP and at the beginning of each script create a model object. Sample script:
<%#page session="false" contentType="text/html; charset=utf-8"
%><%#include file="/libs/foundation/global.jsp"%><%
pageContext.setAttribute("model", new MyModel(slingRequest, slingResponse));
%>
Value from model: ${model.value}
And sample model:
public class MyModel {
private final SlingHttpServletRequest request;
private final SlingHttpServletResponse response;
public MyModel(SlingHttpServletRequest request, SlingHttpServletResponse response) {
this.request = request;
this.response = response;
}
public String getValue() {
// you may use request & response objects here
return "sample value";
}
}
If you like this approach, you may use a framework that makes writing such models easier. Two interesting solutions are:
Sling models
Slice

Also have a look at the BindingsValueProvider.
https://sling.apache.org/apidocs/sling6/org/apache/sling/scripting/api/BindingsValuesProvider.html

Related

Setting my RSS Feed on ROMETOOL with spring boot app

I'm looking for a way to set my RSS Feed with ROMETools. I have a spring boot blog web app. want to embed the RSS feed URL into an email marketing app to read that feed.
The problem is I couldn't find anywhere in the net setting the feed items automatically, for example, everyone setting the URL and description manually like "hi this my description" and also they have the post URL entered manually like "www.domain.postId?id=20"! what I need is the blog URL detected automatically with title, body, etc... Any ideas, anyone has implemented that earlier would be a big favourite. Thanks in advance.
What I have learned is:
1- embed the dependency in POM:
<dependency>
<groupId>com.rometools</groupId>
<artifactId>rome</artifactId>
<version>1.12.2</version>
</dependency>
2-Expose the RSS Feed URL:
#RestController
public class RssFeedRestController {
#Autowired
private RssFeedView view;
#GetMapping("/rss")
public View getFeed() {
return view;
}
}
3-Extend the AbstractRssFeedView as a #Component
#Component
public class RssFeedView extends AbstractRssFeedView {
#Override
protected void buildFeedMetadata(Map<String, Object> model, Channel channel, HttpServletRequest request) {
channel.setTitle("Title"); //Here is my Concern
channel.setDescription("Description"); //Here is my Concern
channel.setLink("www.mydomain.com"); //Here is my Concern
channel.setUri("www.mydomain.com"); //Here is my Concern
}
#Override
protected List<Item> buildFeedItems(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) {
Item item = new Item();
Date postDate = new Date();
item.setTitle("title"); //Here is my Concern
item.setLink("www.mydomain.com/"); //Here is my Concern
item.setUri("/www.mydomain.com/"); //Here is my Concern
item.setPubDate(postDate);
item.setAuthor("Me");
Description description = new Description();
description.setValue("Description"); //Here is my Concern
item.setDescription(description);
return Arrays.asList(item);
}
}

REST Calls from a Liferay Portlet

I'm trying to setup a simple Liferay + Maven portlet that can utilize REST services to fetch data from an external database. I believe I'm most of the way there but I'm stuck on the #RequestMapping within a Liferay portlet. I have a #Controller setup that runs fine on the View phase of the portlet
#Controller
#RequestMapping(value = "VIEW")
public class RiskController {
#ActionMapping
public void handleActionRequest(ActionRequest request, ActionResponse response)throws Exception {
return;
}
#RenderMapping
public ModelAndView handleRenderRequest(RenderRequest request, RenderResponse response, ModelMap model) {
model.addAttribute("helloWord", "123");
return new ModelAndView("index", model);
}
}
Now I'd like to write some service classes and fetch my data, but I'm not sure how to set this up as far as the Paths/URLs are concerned from a Liferay perspective (i.e., localhost:8080/myPortlet/myAjaxCall). I want to do something basic like return an Object via JSON like so
#RequestMapping(value = "/getMyData/123", method = RequestMethod.GET)
public #ResponseBody Data getData(#RequestParam long gcfId) {
Data data = dataRepo.getMyData(123);
return data;
}
Can anyone help get me in the right direction? Can provide more code if needed

Receiving files form PLUpload in WICKET

Im trying to integrate PLUpload into my wicket application. First steps are looking clear. Im able to choose files and when i click the "upload"-button i receive an request on server-side in my PLUploadBehavior based on AbstractDefaultAjaxBehavior. But it does not seems to be a MultiPart request.
public abstract class PLUploadBehavior extends AbstractDefaultAjaxBehavior {
public PLUploadBehavior() {
}
#Override
public void renderHead(final Component component, IHeaderResponse response) {
super.renderHead(component, response);
response.render(JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(PLUploadBehavior.class, "plupload.full.min.js"));
StringBuffer script = new StringBuffer();
//build the init-script...
response.render(OnLoadHeaderItem.forScript(script.toString()));
}
#Override
protected void respond(AjaxRequestTarget target) {
Request request = getComponent().getRequest();
//received request here, but don't know hot to access files
if (request instanceof IMultipartWebRequest) {
System.out.println("Multipart!!!");
}
}
}
I followed the tutorial for plupload and have no form in my html template. There is none in the tutorial, so i think i don't need it. Anyone an idea to access the files on server-side?
After some more coffee i found the solution to my problem. The example on wicket in action can get adapted to the use with an Behavior. Thanks to Martin Grigorov and the great Wicket Team!

Store url when #Controller is accessed Spring MVC

Is there a way to access the URL resolved from a Spring MVC controller - e.g.
#RequestMapping("/{language}/news/{articleId}")
public String newsPage(...) {
}
Resolves to:
/en/news/63421
I'd like to store this with the session so I can keep a track of last place visited. The motivation here is if the page is secured the login filter will come into play and we have used
SavedRequestAwareAuthenticationSuccessHandler
to route users back to the page they were trying to access.
However if they are viewing unsecured pages and choose to log in using a form that drops down from the top of the screen (the page's menu bar) the 'last page' seems to be the login form so the success handler drops them back to the root context.
I'd like to intercept controller calls and store a single URL with the session, override SavedRequestAwareAuthenticationSuccessHandler to allow us to modify the RequestCache and then let Spring redirect on login success.
Ideally we'd like a generic way to do this across all controllers but not sure if there is a filter we can use to pick this up - filtering requests gets all sorts of noise like css, js, images and html fragment pages so we're hoping someone knows a way to do this just with the controllers themselves.
There are two questions:
1) obtain the url in a controller method
#RequestMapping("/{language}/news/{articleId}")
public String newsPage(..., HttpServletRequest request) {
String uri = request.getRequestUri();
...
}
If you need this very often then you can implement a HandlerMethodArgumentResolver. *See this answer https://stackoverflow.com/a/8769670/280244 for an example (it implements a HandlerMethodArgumentResolver for the current user, but you can easyly adapt it for urls)
2.) store the url for each request in the session
You can implement a Servlet Filter or Spring HandlerInterceptor, both get a HttpServletRequest (In a Servlet Filter you need to cast the ServletRequest to an HttpServletRequest first.
Then you can obtain the url and the Session httpServletRequest.getSession() and then store the url in the session.
public class MyFilter implements Filter {
#Override
public void init(final FilterConfig filterConfig) throws ServletException {
//do nothing
}
#Override
public void doFilter(ServletRequest requ, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
if (requ instanceof HttpServletRequest) {
HttpServletRequest httpServletRequest = (HttpServletRequest) requ;
httpServletRequest.getSession().setAttribute(
"myFilter.LAST_URL",
httpServletRequest .getRequestURI());
}
chain.doFilter(request, response);
}
#Override
public void destroy() {
}
}
To get the URL path you can use the HttpServletRequest - so for example you have:
www.mysite.com/en/news/63421
req.getPathInfo() = /en/news/63421
Storing it in the session though could cause problems if someone is to use your site with multiple tabs open.

How to create a servlet on the fly

For below URL's I receive a 404 error, this is fine since the URL's do not exist. Is it possible to create these servlets while the server is running before the error page is returned ?
http://127.0.0.1:8888/test1
http://127.0.0.1:8888/test1/test2
I'm thinking perhaps to create a generic controller that intercepts all urls if the current servlet does not exist, then create it ?
Assuming that by Spring you mean Spring MVC, you could do something like this:
#Controller
public class YourController {
#RequestMapping("/mappingA")
public void methodA() {
// (...)
}
#RequestMapping("/mappingB")
public void methodB() {
// (...)
}
// Catches all non-matched requests.
#RequestMapping("/*")
public void fake404(HttpServletRequest request) {
var uri = request.getRequestURI();
// (...)
}
}

Resources