Extending Liferay UserLocalServiceImpl in an Ext plugin - java

In my Liferay 6.1.1 installation I have extended (note: not overridden) the UserLocalServiceImpl class in an Ext plugin to provide a more relaxed screen name validation. However, I have been unable to get Liferay to load the new class instead of the default UserLocalServiceImpl class.
As far as I can tell, the "normal" way to replace service classes is to use a hook plugin. Unfortunately, hook plugins cannot access the implementation classes. I would have to extend UserLocalServiceWrapper instead of UserLocalServiceImpl, which would be very cumbersome for this particular use.
Is there a way to get Liferay to use my modified service class from an Ext plugin? Alternatively, is there a way to allow a hook plugin access to the implementation classes?

It is possible to change the service class implementation from an Ext plugin using the following procedure:
Create a new folder named META-INF under docroot/WEB-INF/ext-impl/src in the Ext folder.
Create a new file named ext-spring.xml under docroot/WEB-INF/ext-impl/src/META-INF.
Search the Liferay source distribution for the portal-spring.xml file. In Liferay 6.1.1 it can be found at portal-impl/src/META-INF/portal-spring.xml.
Copy the content of portal-spring.xml to the ext-spring.xml file that was created earlier.
Remove all bean entries from ext-spring.xml, except for those that correspond to classes that will be replaced/extended.
For each remaining entry, change the class attribute to point to the replacement class.
Re-deploy the Ext plugin and restart the Liferay application server.

Related

Using SpringExtension with Tomcat and Hibernate web app

We are trying to use spring-test's SpringExtension to write integration tests for our Spring and Hibernate-based Tomcat web application. Our sessionFactory bean configuration has the property configured mappingJarLocations with a sample value as /WEB-INF/lib/company-common*.jar which contains hibernate mapping files. In both actual deployment and Eclipse dev deployment, this works fine as the docBasePath (in Servlet environment) is appended to this pattern and the files are getting resolved. But this is not the case while running JUnit test cases either in a local or a CI environment.
We tried our best to use the provided support by having few overridden implementations of WebTestContextBootstraper, GenricXmlWebContextLoader, XmlWebApplicationContext, and WebDelegatingSmartContextLoader but had to finally give up as we cannot override the final method org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(MergedContextConfiguration) to provide the custom implementation of XmlWebApplicationContext. Our current approach is to manually create the application context and use it in the tests.
Here is the project structure:
Project_WebApp
|--src/**
|--WebContent/**
|--pom.xml
When the app is packaged as Project_WebApp.war, the dependencies are inside WEB-INF/lib from the root of extracted war. When deployed as a webapp in Tomcat using Eclipse, the dependencies are copied to <Eclipse_Workspace_Dir>/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/Project_WebApp/WEB-INF/lib. In both cases, the dependencies are available at <Resource_Base_Path>/WEB-INF/lib and Resource_Base_Path has no relation to Project_WebApp base directory.
Questions:
Did any one use SpringExtension in a scenario similar to above? If so can you suggest any alternative approaches?
Instead of /WEB-INF/lib/company-common*.jar, we tried a classpath-based pattern but didn't work as the obtained class path resources don't match the pattern. Is there anything else to try here?

Vaadin widgetset path is changed after updating to 7.7.0

In my Vaadin application, I have my own widgetset specified like below in web.xml
<init-param>
<param-name>widgetset</param-name>
<param-value>com.foo.bar.AppWidgetSet</param-value>
</init-param>
And, I had placed my AppWidgetSet.gwt.xml file in src/main/java/com/foo/bar/AppWidgetSet.gwt.xml
This setup worked fine until I upgraded to vaadin 7.7.0 (from 7.6.8). After upgrade, I got following error, when I try to access the app through a browser.
INFO: Requested resource [/VAADIN/widgetsets/AppWidgetset/AppWidgetset.nocache.js] not found from filesystem or through class loader. Add widgetset and/or theme JAR to your classpath or add files to WebContent/VAADIN folder.
It seems like vaadin is looking for a different location for the widgetset, so I placed my AppWidgetSet.gwt.xml in the root of the classpath (src/main/java/AppWidgetSet.gwt.xml) and re-built the app.
Then it worked again.
Is specifying the widgetset as an init param no longer available? Do I have to place the widgetset xml in the root of the classpath itself?
I have similar issues after upgrading my Vaadin application from 7.6.8 to 7.7.2. I've noticed that package under src/main/resources started to multiply recursively :
Below was the state with version 7.6.8, prior updating POM to 7.7.7 :
src/main/resources
myPackage
MyAppWidgetset.gwt.xml
After updating POM to 7.7.7, under "myPackage" appeared new "myPackage" with xml file ! Just to emphasize that after every rebuild, those folders constantly creating and creating, so after 4th build there are more than 10 subfolders !
src/main/resources
....myPackage
........myPackage
................MyAppWidgetset.gwt.xml
................................myPackage
................................................MyAppWidgetset.gwt.xml
...
MyAppWidgetset.gwt.xml
It seems as if there is a bug in 7.7.2 as regards custom widgetsets. First, check if you really need them. With no client side custom widgets, just forget any widgetset annotations or any related web.xml parametrization and let Vaadin make use of its new default AppWidgetset. If not, consider refactoring and converting custom client stuff into separate projects, installed in local Maven repo and then used via dependency, still not putting any own gwt.xml anywhere in main project's path. Finally, if none of above may be used (as in my case, too), just wait for bug fix in 7.7.3.
See: https://dev.vaadin.com/ticket/20320
As I noticed, new 7.7.2 plugin does not put anything into source (i.e. /VAADIN/widgetsets), but stores compiled JS directly in output artifact and war archive. So, the workaround for #Lahiru Chandima could be not rely entirely on new, ascetic 7.7.2 plugin and make use of some old elements like <webappDirectory> and/or <hostedWebapp>, mentioning ${basedir}/src... locations.
For #dobrivoje I'd recommend doing compilation as needed, then remove surprisingly created unnecessary (nested) packages and xml file and forget client compilation for some time (is it really needed in every build?) by commenting out Maven goals:
<!-- goal>update-widgetset</goal>
<goal>compile</goal -->

Spring boot configuration in a multi-Module maven project

I'm having a problem properly setting up spring boot for my multi-module maven project.
There is a module "api" that uses another module "core". Api has an application.properties file that contains spring.mail.host=xxx. According to the spring boot documentation this provides you with a default implementation of the JavaMailSender interface, ready to be autowired.
However the class that is responsible for sending out the e-mails resides in the "core" package. When I try to build that module the build fails because no implementation of JavaMailSender can be found.
My guess then was that the mailing config should reside in "core" in a separate application.properties. I created that and moved the spring.mail.host property from the "api" to the "core" property file.
This time the core module builds successfully, but "api" fails to build because of the same exception, so I think I just moved the problem.
I don't understand the required structure for handling this type of situations well enough so I was wondering what the correct way is for having a "core" module containing all the correct configuration for sending mails and having other modules use the mailing code and config that resides in it.
I found the answer in another stack overflow question: How to add multiple application.properties files in spring-boot?
It turns out there can only be 1 application.properties file in the final jar that spring boot creates. To have multiple files you have to rename one of the files to something custom. I named the properties of the core module "core-application.properties".
Then in the API module I added this to the spring boot application class:
#SpringBootApplication
#PropertySource(value = {"core-application.properties", "application.properties"})
Doing this I can correctly use the base properties file and overwrite them in the more specific modules. Also you can still create profile-specific properties file (core-application-production.properties) with this setup, no need to add those to the propertysource manually). Note that #PropertySource does not work for yaml configuration files at this moment.
there is one effective application.properties per project. you just keep 2 properties file for a success build.
when api module use core module, the application.properties in core module is overwrite by api.
Your API's pom.xml must has dependency of CORE module.
the solution is to define properties files as a value of #PropertiesSource in Starter class.
but it is beter to put "classpath:" behind the properties files.
for example in Intellij idea after adding the "classpatch:" word berhind the files name, values become to link. like this:
#SpringBootApplication
#PropertySource(value = {"classpath:core-application.properties", "classpath:application.properties"})
I hope to helped you.

How do I determine which version of a class my object is?

I'm trying to write a plugin into a framework application (Joget). My plugin source looks something like this:
public class MyPlugin extends ExtDefaultPlugin implements ApplicationPlugin, ParticipantPlugin {
...
public void execute(){
...
SecurityContextImpl secContext = (SecurityContextImpl) WorkflowUtil.getHttpServletRequest().getSession().getAttribute("SPRING_SECURITY_CONTEXT");
}
}
When I run the plugin, I get the following exception.
java.lang.ClassCastException: org.springframework.security.context.SecurityContextImpl cannot be cast to org.springframework.security.context.SecurityContextImpl
I'm using Maven. Now since both have the same package name, I'm assuming I'm accidentally using the wrong package version in my plugin JAR (that contains the SecurityContextImpl class) than the one in the framework. But I've double-checked and it looks like I'm including the correct one in my plugin package.
Is there a way to see the classloader or source JAR of my class (e.g. using reflection in some manner)? Any other ideas on how to address this?
This type of java.lang.ClassCastException, where both classes names are equals, occur when the same class, or two class with the same name are loaded by 2 different classloaders.
I don't know Joget, but you are talking about plugin. Frameworks often load plugins in separate classloaders to ensure a proper isolation between them.
Since you say I've double-checked and it looks like I'm including the correct one in my plugin package., you may want to remove spring-security from your package, as it's probably already loaded by the framework classloader.
You're using Maven, so you may simply add <scope>provided</scope> to the spring-security dependency (but not sure, since we don't have your pom.xml)
I've got the same exception when I was running my plugin.
There are two cases in general:
1. The class is a local class.
And that is to say, there is no repository(groupId, artificateId, etc) to be deployed in the pom.xml of your plugin. The solution is, go the target folder and open the xxx-0.0.1-snapshot.jar file, then open META-INF/MANIFEST.MF, add the source file of that class /dependency/file.jar, then add the source jar to the dependency folder
Remarks: It is better to give a version of the your local file and add it as shown in your pom.xml to let it be found as src in your code.
<!-- your source jar need to be renamed as example-1.0.0.jar -->
<dependency>
<groupId>this.should.be.the.prefix.of.your.package</groupID>
<artificateId>file.name<artificateId>
<version>1.0.0</version>
<systemPath>${basedir}/lib/stclient_updated-1.0.0.jar</systemPath>
<scope>system</scope>
</dependency>
2. The class is a remote class with repository
I had this type of problem once because the repository is not correct, see also Maven Repository to find the official repository of the source.
I hope that it could help =)
Cheers

Classloader problem with EJB

I'm working on a project which includes persistence library (JPA 1.2), EJB 3 and Web presentation layer (JSF). I develop application using Eclipse and application is published on Websphere Application Server Community Edition (Geronimo 2.1.4) through eclipse plugin (but the same thing happens if I publish manually). When publishing to server I get the following error:
java.lang.NoClassDefFoundError: Could not fully load class: manager.administration.vehicles.VehicleTypeAdminBean
due to:manager/vehicles/VehicleType
in classLoader:
org.apache.geronimo.kernel.classloader.TemporaryClassLoader#18878c7
at org.apache.xbean.finder.ClassFinder.(ClassFinder.java:177)
at org.apache.xbean.finder.ClassFinder.(ClassFinder.java:146)...
In web.xml I have reference to EJB:
<ejb-local-ref>
<ejb-ref-name>ejb/VehicleTypeAdmin</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>manager.administration.vehicles.VehicleTypeAdmin</local>
<ejb-link>VehicleTypeAdminBean</ejb-link>
</ejb-local-ref>
EJB project has a reference to persistence project, and Web project has references to both projects. I don't get any compilation errors, so I suppose classes and references are correct.
I don't know if it is app server problem, but I ran previously application on the same server using same configuration parameters.
Does anybody have a clue what might be the problem?
Looks almost like it couldn't find the class manager.vehicles.VehicleType when it was attempting to create/load the class manager.administration.vehicles.VehicleTypeAdminBean.
I've encountered similar problems before. When the class loader attempts to load the class it looks at the import statements (and other class usage declarations) and then attempts to load those classes and so on until it reaches the bottom of the chain (ie java.lang.Object). If it cannot find one class along the chain (in your case it looks like it cannot load VehicleType) then it will state that it cannot load the class at the top of the chain (in your case VehicleTypeAdminBean).
Is the VehicleType class in a different jar? If you have a web module and and EJB module do you have the jar containing the VehicleType class in the appropriate place(s). Sometimes with web projects you have to put the jars in the WebContent/WEB-INF/lib folder or it won't find them.
Are both of these projects deployed separately (ie. two ears? or one ear and one war?) or are they together (ie, one ear with jars and a war inside?). I'm assuming the second given you declared your EJB local?
The jars that you are dependent on also have to be declared in your MANIFEST.MF files in the projects that use it.
I'm kind of running on guesses since I do not know your project structure. Showing that would help quite a bit. But I'd still check on where VehicleType is located with regards to your EJB class. You might find it isn't where you think it is come packaging or runtime.
Thanks #Chris for WebContent/WEB-INF/lib idea ! it works for me by following these steps :
1- Export my EJBs to a JAR (MyEJBs.jar)
2- I created another jar with your_installation_path/IBM/SDP/runtimes/your_version/binCreateEJBStrub.bat via CMD.exe, by executing this command :
createEJBStubs.bat <my_path>/MyEJBs.jar -newfile –quiet
3- A new jar will be automatically created in the same directory as MyEJBs.jar named MyEJBs_withStubs.jar
4- Put your new jar in WebContent/WEB-INF/lib
5- Call your EJBs by :
MyEJBRemote eJBRemote;
InitialContext ic = new InitialContext();
obj = ic.lookup("your_ejb_name_jndi");
eJBRemote = (MyEJBRemote ) PortableRemoteObject.narrow(obj,
MyEJBRemote.class);
eJBRemote = (MyEJBRemote ) obj;
Now you can call your EJBs from another EAR

Categories

Resources