JavaMelody with JRuby on Rails + Tomcat - ruby-on-rails

I am trying to add JavaMelody monitoring to a Rails 4.0 app which we deploy to Tomcat running on Windows 2008 R2, with the help of JRuby and Warbler. As described in the JavaMelody user guide, I have added both javamelody.jar and jrobin-1.5.9.jar to WEB-INF/lib/ and extended our web.xml too look essentially like this:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- JavaMelody -->
<filter>
<filter-name>monitoring</filter-name>
<filter-class>net.bull.javamelody.MonitoringFilter</filter-class>
<init-param>
<param-name>log</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>monitoring</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>net.bull.javamelody.SessionListener</listener-class>
</listener>
<!-- JRuby-Rack-->
<filter>
<filter-name>RackFilter</filter-name>
<filter-class>org.jruby.rack.RackFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RackFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.jruby.rack.rails.RailsServletContextListener</listener-class>
</listener>
</web-app>
This seems to work to some extend - there seems to be monitoring information recorded, as I can see that a folder <TOMCAT_HOME>\temp\javamelody is created, and the files therein seem to be updated which each request I make to the app.
But unfortunately, what doesn't work is actually opening the monitoring report. When I go to http://localhost:8080/ourapp/monitoring, I don't get a report page as described in the user guide, but the 404 page of our Rails app instead. The Tomcat logs confirm that both the JavaMelody monitoring filter and SessionListener have been loaded and don't seem to reveal any errors. What have I missed?

since you mapped JRuby-Rack to handle everything (/*) you either need to re-arrange the mapping to make sure the specific path(s) take precedence in being handled by the other filter e.g.
<filter-mapping>
<filter-name>monitoring</filter-name>
<url-pattern>/monitoring</url-pattern>
</filter-mapping>
or alternatively not route everything to JRuby-Rack if the paths it needs to handle can be mapped (you might need to change the monitoring filter paths as well or try using the RackServlet instead if you do not mind "replacing" the container default servel)

Related

Dockerized Alfresco CORS filter

I have a dockerized Alfresco 6.2 community version, clean for now, up and running correctly in my AWS server. I can use it ang log in into share.
Now I want to add my custom app, writtein in Vue.js, which is dockerized too, and make calls to the Alfresco REST APIs to develop my customizations.
When I call any of the APIs I always receive CORS error.
I've tryied many many times, changing Alfresco configuration, Tomcat server configuration, using jar and so on, but nothing has changed.
The error I get is always Access to XMLHttpRequest at 'http://my-alfresco-url/alfresco/api/-default-/public/authentication/versions/1/tickets' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Here is my simplified API call (just for simplicity, the fetch method I use inside my Vue.js app is the same)
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Page Title</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
</head>
<body>
<script>
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Access-Control-Allow-Origin", "*");
myHeaders.append("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS");
myHeaders.append("Access-Control-Allow-Headers","Origin, Content-Type, X-Auth-Token, Access-Control-Allow-Methods, Access-Control-Allow-Origin");
var raw = JSON.stringify({
"userId": "user",
"password": "password"
});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow',
};
fetch("http://my-alfresco-url/alfresco/api/-default-/public/authentication/versions/1/tickets", requestOptions)
.then(response => response.json())
.then(result => console.log(result))
.catch(error => console.log('error', error));
</script>
</body>
</html>
Here is my alfresco-global.properties:
cors.enabled=true
cors.allowed.origins=*
cors.allowed.methods=GET,POST,HEAD,OPTIONS,PUT
cors.allowed.headers=Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers
cors.exposed.headers=Access-Control-Allow-Origin,Access-Control-Allow-Credentials
cors.support.credentials=false
cors.preflight.maxage=1800
I tried changing those parameters, but it didn't work.
I've tried changing tomcat/conf/web.xml or tomcat/webapps/alfresco/WEB-INF/web.xml adding this section
<!-- CORS Filter Begin -->
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
</init-param>
<init-param>
<param-name>cors.exposed.headers</param-name>
<param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
</init-param>
<init-param>
<param-name>cors.support.credentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.preflight.maxage</param-name>
<param-value>1800</param-value>
</init-param>
</filter><!-- CORS Filter End -->
<!-- CORS Filter Mappings Begin -->
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- CORS Filter Mappings End -->
but if I use it as shown then The entire Alfresco is broken, with errors like
provacors-ass_1 | 2021-04-19 12:07:10.007 ERROR (org.alfresco.solr.AlfrescoCoreAdminHandler#29a5f4e7_Worker-24) [ ] o.a.s.t.AbstractTracker Tracking failed for AclTracker - archive
provacors-ass_1 | org.alfresco.error.AlfrescoRuntimeException: 03190007 api/solr/aclchangesets return status:404
provacors-ass_1 | at org.alfresco.solr.client.SOLRAPIClient.getAclChangeSets(SOLRAPIClient.java:169)
provacors-ass_1 | at org.alfresco.solr.tracker.AclTracker.checkRepoAndIndexConsistency(AclTracker.java:338)
provacors-ass_1 | at org.alfresco.solr.tracker.AclTracker.trackRepository(AclTracker.java:303)
provacors-ass_1 | at org.alfresco.solr.tracker.AclTracker.doTrack(AclTracker.java:95)
provacors-ass_1 | at org.alfresco.solr.tracker.AbstractTracker.track(AbstractTracker.java:215)
provacors-ass_1 | at org.alfresco.solr.tracker.TrackerJob.execute(TrackerJob.java:47)
provacors-ass_1 | at org.quartz.core.JobRunShell.run(JobRunShell.java:216)
provacors-ass_1 | at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:563)
I've followed this question without any result: How to resolve CORS error in alfresco webscripts in alfresco sdk?
I've read this forums without any success:
ADF CORS solving strategies
enable-cors-in-alfresco-and-how-to-use.html
Enabling CORS on Alfresco ECM
I also tried using webpack configuration, with Vue, but I'm not so sure I did it correctly. It didn't work.
What am I missing?
How is it possible to use a custom javascript call in another domain with Dockerized Alfresco?
Thanks.
After many trials, I've managed to work. Here is how I did.
First things first, alfresco-global.properties cors options seems to be useless and uneffective. At least for ACS. If there is anyone who can explain me how they work I'll appreciate it.
I needed to add two libraries to my Alfresco 6.2 tomcat/webapps/WEB-INF/lib folder, cors-filter v2.5 and java-property-utils v. 1.9.1. They has to be exactly those versions (not the newer one 2.10 and 1.16) or they won't work with the next web.xml configuration.
I added them to my acs/platform pom.xml
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>java-property-utils</artifactId>
<version>1.9.1</version>
</dependency>
and this is their web.xml configuration, to relax CORS filter:
<!-- CORS Filter Begin -->
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.allowGenericHttpRequests</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.allowOrigin</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowSubdomains</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET, HEAD, POST, PUT, DELETE, OPTIONS</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>origin, authorization, x-file-size, x-file-name, content-type, accept, x-file-type</param-value>
</init-param>
<init-param>
<param-name>cors.supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.maxAge</param-name>
<param-value>3600</param-value>
</init-param>
</filter>
<!-- CORS Filter End -->
<!-- CORS Filter Mappings Begin -->
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/api/*</url-pattern>
<url-pattern>/service/*</url-pattern>
<url-pattern>/s/*</url-pattern>
<url-pattern>/cmisbrowser/*</url-pattern>
</filter-mapping>
<!-- CORS Filter Mappings End -->
note the <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class> value.
To add those values I customized my acs-platform-docker project and added next line to Dockerfile instructions:
# TO ENABLE CORS
COPY web.xml ${TOMCAT_DIR}/webapps/alfresco/WEB-INF/web.xml
obviusly the modified web.xml file was put inside acs-platform-docker resource folder, it needs to be included when the image is built.
If there is another way to handle this, please let me know.

Weblogic reload app throws "No WebApplicationContext found: no ContextLoaderListener registered?" message

I have a grails-2.4.4 application deployed in weblogic 12c. The application works fine. However, when I stop and start the app, all GET action works, but not others [POST, PUT, DELETE, ...].
I got this exception message in console
No WebApplicationContext found: no ContextLoaderListener registered?
I did some search and the solution everybody say is to add this line in web.xml file:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Grails generate its own web.xml file, and inside, this file has the following line:
<listener>
<listener-class>org.codehaus.groovy.grails.web.context.GrailsContextLoaderListener</listener-class>
</listener>
GrailsContextLoaderListener is an inheritance of ContextLoaderListener, so this is not my solution
What should I do?

Filename characters encoding in Jsf 2.2 Upload vs. Apache Commons Upload

Wildfly 8, Omnifaces 2.2, Primefaces 5.2, JSF 2.2.11 (Mojarra)
I am using Ominifaces CharacterEncodingFilter to ensure that file names are encoded correctly on server. Oddly if Primefaces using Jsf internal upload, the file name are not encoded. And if Primefaces use older approach with Appache Commons it is ok.
Example: 'Hällo.jpg' becomes 'Hällo.jpg'
Web.xml configurations:
Apache solution (correct):
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>commons</param-value>
</context-param>
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.omnifaces.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Jsf Upload (characters are not encoded). Other parameters are removed.
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.omnifaces.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
EDIT: due to answer this is a server bug. I've tried to configure the server:
<jboss-web>
<default-encoding>UTF-8</default-encoding>
</jboss-web>
and
<servlet-container name="default" default-encoding="UTF-8">
but it doesn't help.
I reproduced it, WildFly isn't at all considering request request body encoding for multipart/form-data requests. You really have to configure it in server end (like as you would do for GET requests).
Open /standalone/configuration/standalone.xml, peek the following line
<servlet-container name="default">
change it to
<servlet-container name="default" default-encoding="UTF-8">
and restart. This at least worked for me on WildFly 10.0.0. I created issue WFLY-6226 to let it consider request body encoding first so there's no need to edit standalone.xml on that.
In WildFly 8.x (I tested 8.2.1) this unfortunately still won't work as it does not at all consider the above setting. Your best bet is to keep using Apache Commons FileUpload until you can upgrade WildFly.
If you really want to keep native upload, then you could consider to explicitly decode the broken filename to bytes using ISO-8859-1 and then re-encode it using UTF-8.
String fileName = new String(uploadedFile.getFileName().getBytes("ISO-8859-1"), "UTF-8");
This is however brittle and not portable as it would break when deployed to a server where this encoding problem doesn't manifest. So you really need to remember to revert the workaround when upgrading/migrating.

Apache Shiro No FilterChainResolver configured. Returning original FilterChain

I was configuring my application to use apache shiro security, However, I keep getting the following in my log output:
DEBUG o.a.s.w.servlet.AbstractShiroFilter - No FilterChainResolver configured. Returning original FilterChain.
My .ini file looks like this at the moment:
[main]
cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
securityManager.cacheManager = $cacheManager
authc = org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
authc.loginUrl = /login.xhtml
[users]
admin = password
[urls]
/login.xhtml = authc
/logout = logout
/secured/** = authc
The relevant snippet from my web.xml is as follows:
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
I am using Apache Shiro 1.2 on a tomcat 7 container
Strange that there are not so many questions addressing this issue, what did I overlook?
Looks like I was using a blank shiro.ini file. I rectified this and now I can see shiro is catching the write URLs

Pluto 2.0 + MyFaces Portlet bridge + JSF 2.0 Application

Recently I have explored the possibilities to integrate a regular JSF 2.0 application as a portlet a portlal.
The first thing I've done is downloaded Pluto 2.0 (bundled with tomcat) and Myfaces Portlet Bridge 2. I have created a small webapp (Core JSF 2.0 chapter 2 quiz application).
As I saw from the tutorials I have created portlet.xml file in WEB-INF with the following content:
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd">
<portlet>
<portlet-name>QPortlet</portlet-name>
<portlet-class>javax.portlet.faces.GenericFacesPortlet</portlet-class>
<expiration-cache>0</expiration-cache>
<init-param>
<name>javax.portlet.faces.defaultViewId.view</name>
<value>faces/index.xhtml</value>
</init-param>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<supports>
<mime-type>application/xhtml+xml</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>QPortlet</title>
<short-title>QPortlet</short-title>
</portlet-info>
</portlet>
</portlet-app>
Then I added several lines in the web.xml:
<servlet>
<servlet-name>QPortlet</servlet-name>
<servlet-class>org.apache.pluto.container.driver.PortletServlet</servlet-class>
<init-param>
<param-name>portlet-name</param-name>
<param-value>QPortlet</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>QPortlet</servlet-name>
<url-pattern>/PlutoInvoker/QPortlet</url-pattern>
</servlet-mapping>
Have copied the corresponding bridge Jar to the lib folder, packaged as war file and deployed to Pluto. Pluto itself recognized my webapp as a portlet. Cool but when I opened the window with the portlet it was just empty. The web application works nice separately, But not as a portlet.
I have tried the examples from MyFaces but the most I can get is the following exception:
Error rendering portlet portlet-bridge-carstore.
java.lang.IllegalArgumentException: Only supported in a portlet environment
at org.apache.myfaces.portlet.faces.util.map.PortletRequestMap.(PortletRequestMap.java:42)
…
Am I doing something wrong?
I have also tried JBoss Portlet Bridge, but I get the same result…

Resources