Omit the minus "-" in Liferay friendly URL - liferay

I've created a friendly URL file for my abc-portlet (the portlet uses the DefaultFriendlyURLMapper):
<routes>
<route>
<pattern>/{urlTitle}</pattern>
<implicit-parameter name="p_p_lifecycle">0</implicit-parameter>
<implicit-parameter name="struts_action">/view</implicit-parameter>
</route>
</routes>
This works like a charm, but I would like to understand, if there's a way to omit the "-" in the friendly URL?
I.e.
http://.../page/-/abc/title
should be
http://.../page/abc/title

I found the solution.
You have to extend the DefaultFriendlyURLMapper and override the isCheckMappingWithPrefix method. (..and of course define this class as your FriendlyURLMapper.)
public class FriendlyUrlWithoutMinus extends DefaultFriendlyURLMapper {
#Override
public boolean isCheckMappingWithPrefix() {
return false;
}
}

Related

How do I open a browser window/tab from blazor webassembly project behind code:

I'm converting a UWP app to Blazor WebAssembly with ASP.NET Core hosted.
I have my markup code in Index.razor and behind code in Index.razor.cs.
In the UWP project I opened a browser window from an onclick function like this:
var success = Windows.System.Launcher.LaunchUriAsync(targetPage);
What can I use in my Blazor project onclick event, that won't lead to "unhandled error has occurred"?
You can open a tab by making use of the 'window.open' function:
#inject IJSRuntime JSRuntime;
....
await JSRuntime.InvokeAsync<string>("open", $"https://www.mysite/mypage", "_blank");
if the page is internal to your website you can use the base uri:
#inject NavigationManager Navigation
#inject IJSRuntime JSRuntime;
...
await JSRuntime.InvokeAsync<string>("open", $"{Navigation.BaseUri}/mypage", "_blank");
You case use below way
razor file
JSRuntime.InvokeVoidAsync("OpenWindow");
html file
<script>
function OpenWindow() {
window.open('https://www.google.com', 'Test', 'width=800,height=860,scrollbars=no,toolbar=no,location=no');
return false
}
</script>
These are great answers and I took it one step further to make a re-usable component. My app uses anchors and link buttons so I have a quick-and-dirty switch for each.
ExternalLink.razor
#inject IJSRuntime JSRuntime
#if (Type == "link")
{
#(Text ?? Url)
}
else if (Type == "button")
{
<button type="button" class="btn btn-link" #onclick="OpenWindow">#(Text ?? Url)</button>
}
#code {
[Parameter]
public string Url { get; set; }
[Parameter]
public string Text { get; set; }
[Parameter]
public string Type { get; set; } = "link";
private async Task OpenWindow()
{
await JSRuntime.InvokeAsync<string>("open", Url, "_blank");
}
}
Usage
<ExternalLink Url="https://www.ourwebsite.com/" Text="Visit Us!" />
<ExternalLink Url="https://stackoverflow.com/" />
<ExternalLink Url="https://duckduckgo.com/" Type="button" />
Why not just use the build in NavigationManager?
Navigation.NavigateTo(a_url, true);
The trick is to use the force parameter.
Happy coding.

How do I map URLs to resources instead of JSF pages?

I'm very used to Jax-RS and the ability to make data available to the caller through custom URLs like:
/bicycles/by_color/blue
by doing:
#Path("{searchCategory}/{searchParam}")
List<Item> get(#PathParam....
What is the equivalent in JSF? I have an application with a ReST API and would like to display a template page, grabbing a specific entity from the database according to part of the URL for the xhtml page to get data from that will be displayed.
I've seen examples with query parameters like '?id=5&pages=true' but nothing with URL mapping like '/5/true.' How do I accomplish this?
For those Googling for an actual answer to the question, PrettyFaces is one way of doing this. It does URL 'beautification,' which includes making elements of the URL's path into receivable parameters.
I'm going to give an example using JAX-RS, then the equivalent with PrettyFaces:
Jax-RS
#Path("user")
public class UserEndpoint{
#PersistenceContext
EntityManager em;
#GET
#Path("{userid}")
public UserEntity getUser(#PathParam("userid")long userId){
return em.find(UserEntity.class, userId);
}
}
JSF with PrettyFaces
Good help for it on here: http://www.ocpsoft.org/prettyfaces/
Backing Bean
#Named
public class UserViewController{
#PersistenceContext
EntityManager em;
public UserEntity getUser(){
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
Map<String, String> params = ec.getRequestParameterMap();
long userId = Long.valueOf(params.get("userid"));
return em.find(UserEntity.class, userId);
}
}
pretty-config.xml (special file that must be created inside the WEB-INF folder)
<pretty-config xmlns="http://ocpsoft.org/schema/rewrite-config-prettyfaces"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ocpsoft.org/schema/rewrite-config-prettyfaces
http://ocpsoft.org/xml/ns/prettyfaces/rewrite-config-prettyfaces.xsd">
<url-mapping id="view-user">
<pattern value="/user/#{userid}" />
<view-id value="/user/view.xhtml" />
</url-mapping>
</pretty-config>

Camel POJO producing with JAXB data format exception

I am using Camel 2.10.3
Here is my camel context:
<camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring">
<endpoint id="webserviceStart" uri="direct:webserviceStart"/>
<dataFormats>
<jaxb id="jaxb" prettyPrint="true"
contextPath="com.jaxbtest.package" />
</dataFormats>
<route id="myRoute">
<from ref="webserviceStart" />
<marshal ref="jaxb" />
<to uri="spring-ws:http://wshost:8010/service"/>
<unmarshal ref="jaxb" />
</route>
</camelContext>
This code works:
#Component
public class WebserviceClient
{
#EndpointInject( ref = "webserviceStart" )
ProducerTemplate _producer;
public Response invoke( Request input )
{
return ( Response ) _producer.sendBody( input ).getOut().getBody();
}
}
This code (following the "Hiding the Camel APIs from your code using #Produce" section of http://camel.apache.org/pojo-producing.html) does not:
#Component
public class WebserviceClient
{
public static interface MyWebservice
{
Response invoke( #Body Request body );
}
#EndpointInject( ref = "webserviceStart" )
MyWebservice _producer;
public Response invoke( Request input )
{
return ( Response ) _producer.invoke( input );
}
}
it throws an exception:
Caused by: java.io.IOException: javax.xml.bind.JAXBException: class org.apache.camel.component.bean.BeanInvocation nor any of its super class is known to this context.
at org.apache.camel.converter.jaxb.JaxbDataFormat.marshal(JaxbDataFormat.java:103)
at org.apache.camel.processor.MarshalProcessor.process(MarshalProcessor.java:59)
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73)
If this is a known bug in camel does anyone know the issue that is related to it? Should I create a new JIRA for this? This seems to be such a simple use case of POJO producing.
Generally, when you get this error, it means you haven't set the list of classes on the JAXB context.
You'd do in JAVA DSL -
JAXBContext context = JAXBContext.newInstance('your classes');
JaxbDataFormat jaxb = new JaxbDataFormat();
jaxb.setContext(context);
and then use your custom dataformat 'jaxb' as your marshal/unmarshal ref.
Thanks!

Embedding a link (or other html) in a JSF message

I want to embed a link in a JSF message, is this possible?
When I try it, the rendered html of the h:messages tag escapes the html characters. I tried setting the escape attribute of the h:messages tag to false, but that didn't help.
Unfortunately, this is not possible in the standard JSF implementation. The component and the renderer doesn't officially support this attribute. You can however homegrow a renderer which handles this.
Since this is a pretty common requirement/wish, I thought to take a look what's all possible.
First some background information: JSF by default uses ResponseWriter#writeText() to write the tag body, which escapes HTML by default. We'd like to let it use ResponseWriter#write() instead like as with <h:outputText escape="false" />. We'd like to extend the MessagesRenderer of the standard JSF implementation and override the encodeEnd() method accordingly. But since the MessagesRenderer#encodeEnd() contains pretty a lot of code (~180 lines) which we prefer not to copypaste to just change one or two lines after all, I found it better to replace the ResponseWriter with a custom implementation with help of ResponseWriterWrapper wherein the writeText() is been overriden to handle the escaping.
So, I ended up with this:
package com.example;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.context.ResponseWriterWrapper;
import javax.faces.render.FacesRenderer;
import com.sun.faces.renderkit.html_basic.MessagesRenderer;
#FacesRenderer(componentFamily="javax.faces.Messages", rendererType="javax.faces.Messages")
public class EscapableMessagesRenderer extends MessagesRenderer {
#Override
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
final ResponseWriter originalResponseWriter = context.getResponseWriter();
try {
context.setResponseWriter(new ResponseWriterWrapper() {
#Override
public ResponseWriter getWrapped() {
return originalResponseWriter;
}
#Override
public void writeText(Object text, UIComponent component, String property) throws IOException {
String string = String.valueOf(text);
String escape = (String) component.getAttributes().get("escape");
if (escape != null && !Boolean.valueOf(escape)) {
super.write(string);
} else {
super.writeText(string, component, property);
}
}
});
super.encodeEnd(context, component); // Now, render it!
} finally {
context.setResponseWriter(originalResponseWriter); // Restore original writer.
}
}
}
In spite of the #FacesRenderer annotation, it get overriden by the default MessagesRenderer implementation. I suspect here a bug, so I reported issue 1748. To get it to work anyway, we have to fall back to the faces-config.xml:
<render-kit>
<renderer>
<component-family>javax.faces.Messages</component-family>
<renderer-type>javax.faces.Messages</renderer-type>
<renderer-class>com.example.EscapableMessagesRenderer</renderer-class>
</renderer>
</render-kit>
Then, to trigger it, just do:
<h:messages escape="false" />
And it works! :)
Note: the above affects <h:messages> only. To do the same for <h:message>, just do the same, but replace anywhere "Messages" by "Message" (component family, renderer type and classnames).
The escape="false" attributed you need is provided by the OmniFaces <o:messages> component. The OmniFaces utility library is available for JSF 2.
I posted this solution mentioned by #BalusC's comment as an answer since this is the most straightforward solution.

Not getting image in h:graphicImage in JSF

I have this very strange error with h:graphicImage
This code works fine :-
<h:graphicImage value="/Common/Images/#{item.templatePicName}"/>
And this one doesn't :-
<h:graphicImage alt="${app:getCommonImagePath(item.templatePicName)}" value="${app:getCommonImagePath(item.templatePicName)}" />
It only shows alt value /Common/Images/Sunset.jpg which is perfectly fine and works in 1st case. Then why doesn't it work in 2nd case? There are no problems with my images. They are present in right directory.
here getCommonImagePath is my custom EL function, whose definition is :
package Common;
public final class AppDeployment {
private AppDeployment(){ //hide constructor
}
private static String commonImageFolderPath = "/Common/Images/";
public static String getCommonImagePath(String picName){
return commonImageFolderPath + picName;
}
}
With JSF you should use #{..} rather than ${..}.
Then check the HTML that is generated to see what the src of the generated image is pointing to.
Then check whether your custom tag is mapped properly.
Its easier to solve if you have a property in your app class that concatenates what you want.
ie:
class App {
private String commonImagePath="/Common/Images/";
//getters and setters
}
Then you would write:
<h:graphicImage alt="#{app.commonImagePath}#{item.templatePicName}" value="#{app.commonImagePath}#{item.templatePicName}" />

Resources