Sending custom objects across portlets in liferay - liferay

I'm having serious issues trying to send share custom objects between portlets in liferay. I have a Hook Plugin, with a servlet filter, which loads an object of Type MyCustomClass and inserts it into the request object as a parameter.
When i try to read this object in a portlet's render() i get a ClassCastException, though i am casting the object to the same class.
I understand that liferay plugins have different contexts, and i already tried to change the classloader before loading the object in the bean and portlet like this:
ClassLoader portalcl = PortalClassLoaderUtil.getClassLoader();
ClassLoader currentcl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(portalcl);
//do my stuff
Thread.currentThread().setContextClassLoader(currentcl);
however, it did not solved the problem, and the only way i found to solve the problem is to serialize the object into a json string, and deserialize it whenever i need it.
Isn't this kinda lame ? Does anyone know a better solution ?
Regards, DS

It sounds like the main problem you're seeing is that two different class loaders are loading the class which techncally makes them different classes (which it seems like you've already determined).
I haven't used LifeRay much but this has been a problem I've seen on other platforms as well. We were using WebSphere and solved this problem by putting the common MyCustomClass into a shared library that was on the server classpath. This way the server will load the class and make it available to all applications on the server through the server's single classloader. If you let each application load the class then you'll keep seeing this exception.

Related

Are jaxrs 1.1 (WLP 8.5) annotated methods thread safe?

I am using jaxrs1.1 jar shipped with Websphere liberty profile 8.5 for creating REST WebService.
Lets suppose we have a method addNewProject as shown below :
If many people call this webservice method to add project concurrently. using link below , are there any concurrency issue? In servlet, each request is a separate thread , is it the same case here or should we handle concurrency by ourselves ?
endpointLink: http://somehost.com/path1/path2/addprojectdetails and POST the JSON object.
#POST
#Path("addprojectdetails")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response addNewProject(ProjectDetails projectdetailsObj) {
return Response.status(200).entity("Project"+projectdetailsObj.getProjectname()+"successfully added").build();
}
I'm not sure what kind of concurrency issues you might be thinking of. The object itself can be either a singleton or request scoped (if using CDI) or a stateless session bean (if using EJB). If you're using a singleton, then you may need to be thread aware and not store state within the class.
It would probably help to understand what kind of concurrency issues you had in mind to answer more thoroughly.

ClassLoader - Loading and saving data

Hopefully someone can help me with this.
It is my understanding that using a ClassLoader is the most reliable way to load in content.
public class Pipeline{
public static URL getResource(String filename) {
return ClassLoader.getSystemResource(filename);
}
public static InputStream getResourceAsStream(String filename) {
return ClassLoader.getSystemResourceAsStream(filename);
}
}
If you had a file at "[jar bundle]/resources/abc.png" ..You would load it by:
URL url = Pipeline.getResource("resources/abc.png");
Loading is simple.
Saving is what's getting me.
I have a program that collects data while running, saves that data on exit, and then loads the data back in next time and keeps adding to it.
Easiest solution I think would be to save back into the jar bundle so that ClassLoader can get at them. Is this even possible? Or recommended?
I don't mind having my resources outside of the jar, just as long as I don't have to resort to 'File' to get at them and save to them. (Unless it can be done cleanly)
folder/application.jar
folder/resources/abc.png
If you could ../ back one from where the ClassLoader is looking it would be easy to cleanly get data from the directory that actually contains the jar file
Pipeline.getResource("../resources/abc.png");
Any ideas?
This isn't really what class loaders are meant for. Loading resources from the class loader is meant so that you can bundle up your application as one package and components can read each other without worrying about how the system you're deploying to is setup.
If the file in the JAR is meant to be changed by the app, then it isn't part of the app and thus probably shouldn't be in the JAR.
I don't have a lot of context on your app, but hopefully my suggestion will be valid for your situation.
I recommend setting a requirement in your app that it has a work area to which it is allowed to read and write and accept a configuration setting that specifies where this directory is. Typical ways to do this in Java are with environment variables, system properties or JNDI settings (for container deployments).
Examples:
Tomcat's startup scripts figure out where it is installed and sets a system property called catalina.home and allows you to over-ride it with an environment variable called CATALINA_HOME.
JBoss looks for JBOSS_HOME
Java application servers typically look for JAVA_HOME to find the JDK.

How to override property "sites.email.membership.reply.body" in liferay

I want override the following properties in my portal-ext.properties:
sites.email.membership.reply.subject=com/liferay/portlet/sites/dependencies/email_membership_reply_subject.tmpl
sites.email.membership.reply.body=com/liferay/portlet/sites/dependencies/email_membership_reply_body.tmpl
sites.email.membership.request.subject=com/liferay/portlet/sites/dependencies/email_membership_request_subject.tmpl
sites.email.membership.request.body=com/liferay/portlet/sites/dependencies/email_membership_request_body.tmpl
to something like this:
sites.email.membership.reply.subject=com/krishna/email_membership_reply_subject.tmpl
sites.email.membership.reply.body=com/krishna/email_membership_reply_body.tmpl
sites.email.membership.request.subject=com/krishna/email_membership_request_subject.tmpl
sites.email.membership.request.body=com/krishna/email_membership_request_body.tmpl
I have done this in EXT, i.e. I have created the package: ext-impl/src/com/krishna/ in EXT-plugin and it works fine, but I am not able to do this in a hook or portlet. Why? Because its giving me exception:
java.io.IOException: Unable to open resource in class loader com/krishna/email_membership_request_subject.tmpl
So, my question: Is there a way to do it in hook or portlet or only EXT can be used?
Thanks
This can be done only in an EXT plugin. Because of the following two reasons:
Hooks can be advantageous to override few properties/services but not all. This particular property is not supported by hooks.
This is definitely not possible with portlets, as you already are facing class loading issues. As portal-impl.jar is located inside the ROOT/WEB-INF/lib of liferay and your portlet doesn't have access to it.
So EXT plugin is the only way.

Client Browser detection in Vaadin

I want to set different themes to my Vaadin application, depending on the user agent.
In particular I want to distinguish at least between mobile devices (iPhone, Android,...) and desktop web browser.
Vaadin's API reveals two interesting classes:
BrowserInfo
WebBrowser
BrowserInfo seems to do the job perfectly for my needs, but fails on instancing via its get-method:
SEVERE: javax.servlet.ServletException: ...
Caused by: java.lang.UnsatisfiedLinkError: com.vaadin.terminal.gwt.client.BrowserInfo.getBrowserString()Ljava/lang/String;
Couldn't find a way to access WebBrowser from within my application either.
Did I choose the right approach for browser distinction?
Why does accessing BrowserInfo fail?
As #quickanalysis pointed out, you've to be aware of the separation of client-/server-side components.
For getting the user agent string on server-side, the following code snippet does the job:
ApplicationContext context = this.getContext();
if (context instanceof WebApplicationContext) {
String userAgent = ((WebApplicationContext)this.getContext()).
getBrowser().getBrowserApplication();
}
From what class you are trying to call this method? The BrowserInfo is available at client-side as WebBrowser ar the server-side. Take a look at the package naming.

Binsor and log4net

I'm using Castle Windsor and Binsor to use dependency injection in my application. I'm no expert at either one. Usually I can figure out how to bend Windsor to my will, but I find Binsor much harder, especially since I haven't found any decent documentation for it.
I'm trying to create a binsor configuration file where I use logging. I configure logging using the following binsor code:
facility LoggingFacility:
loggingApi = LoggerImplementation.Log4net
configFile = "ParasiteLogConf.log4net"
This works great, all components that are registered with the container and that takes an ILogger object as an argument to the constructor will receive the correct ILogger instance.
However, what I want to do now is to use another logger for one specific component. I want that component to log to a file, whereas the other components should only log to screen. How would I go about expressing that using Binsor code?
Aynede#Rahien is your friend here. He has many blog posts on using and configuring Binsor.
For the special logger, you need to add it as a component and then explicitly set the logger property of the dependent component to the id of the special logger component.

Resources