Wicket generate BookmarkablePageLink or Link from URL String - wicket

My final goal is to generate a go back button in my wicket site forms.
Right now I'm able to get the referrer with:
HttpServletRequest req = (HttpServletRequest)getRequest().getContainerRequest();
l.info("referer: {}", req.getHeader("referer"));
This works and I get the whole URL (as a String) but I'm unable to generate a Link object from this.
I'm not sure about the internals although I've been seeing the code for Application.addMount, IRequestHandler and more, I'm not able to find exactly where a URL is converted to what I need to generate a BookmarkablePageLink: the Class and the PageParameters.
P.S. I know this can be done with JavaScript, but I want to serve users without JS active.
Thanks
Possible solution I'm currently using:
public static WebMarkupContainer getBackButton(org.apache.wicket.request.Request request, String id) {
WebMarkupContainer l = new WebMarkupContainer(id);
HttpServletRequest req = (HttpServletRequest)request.getContainerRequest();
l.add(AttributeModifier.append("href", req.getHeader("referer")));
return l;
}
In my markup I have:
<a wicket:id="backButton">Back</a>
And then, in my Page object:
add(WicketUtils.getBackButton(getRequest(), "backButton");
If anyone has any better idea, I'm leaving this open for a while.

You should be able to use an ExternalLink for this.
Something resembling
public Component getBackButton(org.apache.wicket.request.Request request, String id) {
HttpServletRequest req = (HttpServletRequest)request.getContainerRequest();
String url = req.getHeader("referer");
return new ExternalLink(id, url, "Back");
}
with html
this body will be replaced
And your Page object code unchanged.

Related

CustomAction Types in AEM From Component

I am creating a form using form-components. I have email-field and UserName field. I want to send an email to the given email id on click of submit button. In the form I select my custom action type which invoke a servlet which is responsible to send an email. My custom action type has only forward.jsp as script file :
<%#page import="com.day.cq.wcm.foundation.forms.FormsConstants"%><sling:defineObjects/><%
System.out.println(":::::::::::::::"+resource.getPath());
FormsHelper.setForwardPath(slingRequest, resource.getPath() + ".custommail.html");
FormsHelper.setRedirectToReferrer(request, true);
%>
I can see my forward.jsp is getting called when i click submit button, as i can see resourcePath(content/geometrixx/en/toolbar/newsletter/jcr:content/par/start) in stdout.log. But servlet not getting call, In case i hit localhost:4502/content/geometrixx/en/toolbar/newsletter/jcr:content/par/start.custommail.html servlet gets invoke, don't know why its not invoking with FormsHelper.
And also how can we pass parameter i.e. email-field to servlet.
Any Idea.
Thanks
You need to have a servlet registered to your form start component and the proper selector. If you are using the foundation form this would be something like this:
#SlingServlet(resoruceTypes = "foundation/components/form/start", methods = "POST", selectors = "custommail", extenstions = "html", generateComponent = false)
public class CustomMailServlet extends SlingAllMethodsServlet {
#Override
protected void doPost(final SlingHttpServletRequest request, final SlingHttpServletResponse response) throws ServletException, IOException {
//your code here
}
}
Checkout this blog http://labs.sixdimensions.com/blog/2012-08-20/sending-email-adobe-cq-api/ to get and understanding of Email functionality in AEM.

Jaxrs QueryParam as a sub or a root item

Hi the design document I'm working off of wants me to have a URL in the pattern of
<root>/v1/installs/XYZ123/actions/next?app=1234ABCD HTTP/1.1
However the only examples I can find are extremely simple, and only show URLs that would end at the /next.
http://www.mkyong.com/webservices/jax-rs/jax-rs-queryparam-example/
I'm thinking it's something like... ? I'm missing a key step
#GET
#Produces({ "application/json" })
#Path("v1/installs/{id}/actions<SOMETHINGHERE?>/next HTTP/1.1")
public Response getSetupCommands(#PathParam("id")
String id,#QueryParam("next") String next) {
I'm using jboss and jaxrs
Why do I get the feeling that HTTP/1.1 should not be a part of the URL. You may have read/understood the design document incorrectly. If it was saying that the request should look like
GET /v1/installs/XYZ123/actions/next?app=1234ABCD HTTP/1.1
Then you only need to be worried about /v1/installs/XYZ123/actions/next?app=1234ABCD. HTTP/1.1 is simply the HTTP version that will be used implicitly with every request and response.
Your original example was fine, exception you should have replaced #QueryParam("next") with #QueryParam("app"). next is actually part of the path.
This /v1/installs/{id}/actions/next should be what's included in #Path.
The complete semantics of this request URL seems to read something like:
Get the next (resource) controller, and we will use the app query parameter as an argument to pass to this controller.
UPDATE: with example
#Path("/v1")
public class QueryResource {
#GET
#Path("/installs/{id}/actions/next")
public Response getResponse(#PathParam("id") String id,
#QueryParam("app") String app) {
StringBuilder sb = new StringBuilder();
sb.append("ID: ").append(id).append("<br/>");
sb.append("app param: ").append(app);
return Response.ok(sb.toString()).build();
}
}
Browser Test
Fire bug
v1/installs/{id}/actions/{next : .+}
public Response getSetupCommands(#PathParam("id") String id,#PathParam("next") String next) {
Way too hackish for my tastes, but I don't have any control in this situation..

Play Framework redirect not working in Safari

I'm attempting to query Solr from Angular and routing the request through a Play Controller for security and using Play redirect to forward the request to Solr.
This seems to be working on Chrome but not on Safari/Firefox.
Angular ajax request
var solrUrl = '/solr';
storesFactory.getAdvancedMessages = function (searchCriteria, searchType) {
var filterQuery = solrQueryComposer(searchCriteria);
$log.warn(filterQuery);
return $http({
method: 'GET',
url: solrUrl,
params: { 'q': '*',
'fq': filterQuery,
'rows': 30,
'wt': 'json'}
}).
then(function(data, status, headers, config) {
$log.debug(data.data.response.docs);
return data.data.response.docs;
},
function(error){
$log.error(error.message);
});
Play Controller
import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.Security;
#Security.Authenticated(Secured.class)
public class SolrController extends Controller {
private static String solrUrl = "http://whatever.com:5185/solr/select/";
private static String queryPart = "";
public static Result forward(){
queryPart = request().uri().substring(5);
System.out.println(queryPart);
return seeOther(solrUrl+queryPart);
}
}
Play Route
GET /solr controllers.SolrController.forward()
First of all, I'd like to clarify what you're doing.
Play is not forwarding anything here, it's sending a redirect to the client, asking to fetch another URL. The client will send a request, receive a redirect, and send another request.
Which means:
this controller is not "forwarding" anything. It's just tells the client to go somewhere else. ("seeOther", the name speaks for itself).
It's not secure at all. Anyone knowing solr's URL could just query it directly.
since the query is performed by the client, it may be stopped by the cross-domain security policy.
Moreover, There's a HUGE race condition waiting to happen in your code. solrUrl and queryPart are static, therefore shared by all threads, therefore shared by all clients!!
There's absolutely no reason for queryPart to be static, and actually, there's absolutely no reason for it to be in this scope. This variable should be defined in the method body.
I'd also like to point out that request().uri().substring(5) is very brittle and is going to break if you change the URL in the route file.
In return seeOther(solrUrl+queryPart), queryPart arguments keys and values should also be URLencoded.

Issue with FB C# SDK Get method, it works with static string but not with an string formed with variables

I'm working with FB C# SDK. Probably my question is very basic but I have already tried tons of options and I can't solve my problem.
I'm using the get method to retrieve info from facebook, it works perfectly with albums, so it isn't a problem of access_token or initialization.
This is the line of code that I use and it returns me the object with the information of albums, for any user it will be always the same since the app asks for all his albums. It works fine:
dynamic fotos = client.Get("me/albums");
The problem comes when I ask for photos, because it's nos an static value like with albums, it's a value based on user selection, so, I use a variable instead:
public ActionResult Photos(string albumstring)
{
... more code asking for token, etc.
dynamic fotos = client.Get(albumstring);
There it fails and it returns me an empty object. The string text at albumstring is exactly the one needed: "10150240194251714/photos" but it just don't work.
I tested it staticly like this, and it works!:
public ActionResult Photos(string albumstring)
{
... more code asking for token, etc.
albumstring2 = "10150240194251714/photos";
dynamic fotos = client.Get(albumstring2);
But it only works if it's an static value, mixing it with a variable makes it fail, like in this example:
public ActionResult Photos(string albumId)
{
... more code asking for token, etc.
albumstring = albumId + "/photos";
dynamic fotos = client.Get(albumstring);
I have tried a lot of different ways to construct the string like StringBuilders, adding the escape char \, contructing it from the view and bringing it complete to the controller, etc. But it seems that if the string is not directly written it just won't work.
Probably it's an error from the fb c#sdk, but I need to workaround it and I'm out of ideas.
this is the method I use and it works fine to retrieve some album photosm where the class AlbumPhoto is just a DTO to capture de data. I hope it helps
public static List<AlbumPhoto> GetAlbumPhotos(string userAccessToken, string albumId)
{
var list = new List<AlbumPhoto>();
var client = new FacebookClient(userAccessToken);
dynamic photos = client.Get(String.Format("/{0}/photos", albumId));
foreach (var photo in photos.data)
{
lista.Add(new AlbumPhoto
{
FacebookId = photo.id,
Name = photo.name,
ImageUrl = photo.source,
Height = (int)photo.height,
Width = (int)photo.width
});
}
return list;
}

Pull generated HTML programmatically vs. a HttpWebRequest

For our newsletter, I generate the final body of the email in a web page and then want to pull that into the body of the email. I found a way to do that with HttpWebRequest.
private string GetHtmlBody(Guid id)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format("http://news.domain.com/News/View/{0}", id.ToString()));
HttpWebResponse responce = (HttpWebResponse)request.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(responce.GetResponseStream());
return sr.ReadToEnd();
}
However, I feel there has to be a better way. Can I somehow pull the generated view without making a web call?
You could use MVCContrib for this task.
Or try to roll some ugly code:
public static string ViewToString(string controlName, object viewData)
{
var vd = new ViewDataDictionary(viewData);
var vp = new ViewPage { ViewData = vd };
var control = vp.LoadControl(controlName);
vp.Controls.Add(control);
var sb = new StringBuilder();
using (var sw = new StringWriter(sb))
using (HtmlTextWriter tw = new HtmlTextWriter(sw))
{
vp.RenderControl(tw);
}
return sb.ToString();
}
and then:
var viewModel = ...
string template = ViewToString("~/Emails/EmailTemplate.ascx", viewModel);
Assuming the the email code is in the same project as the website, then you should be able to call the action method, get the ActionResult back, then call the ExecuteResult method. The downside is that in order to do it this way, you will need to set it up such that the ExecuteResult will write to a stream that you can take advantage of. In order to do all of this, you will need to mock up some of the classes used by the ControllerContext.
What would probably be a better way (though will likely take more work), is to have the markup you want be generated by an XSLT transform. XSLT is a type of XML document template that can be merged with an XML document that holds data to produce a desired result. If you do this, then you can have your process that sends out emails run the transform as well as have your website run the transform. The advantage of this, is that if you want the markup to be different (i.e. you are redesigning thew newsletter), you will simply need to update the XSLT file and deploy it.
HTH
Finally got a working solution. After finding some proper search terms (thanks to #Darin) any many, many trials I found a solution that works. Putting this in my controller then passing the rendered string into my EmailHelper works great for what I needed.