security permission for java client inside Glassfish V4

782 views
Skip to first unread message

Rajeev Jha

unread,
Jan 30, 2015, 2:13:05 PM1/30/15
to rabbitm...@googlegroups.com
Hi

I am using rabbitmq Java client (3.4.3) as part of Glassfish V4.0 to send data to a rabbitmq server (queue) running on another machine. The logs used to show entries like, 

[2015-01-30T16:26:04.063+0000] [glassfish 4.0] [INFO] [] [javax.enterprise.system.core.security] [tid: _ThreadID=22 _ThreadName=http-listener-1(5)] [timeMillis: 1422635164063] [levelValue: 800] [[
4745   JACC Policy Provider: Failed Permission Check, context(sensordb/sensordb)- permission(("java.lang.RuntimePermission" "modifyThread"))]]

When examining rabbitmq client code, I could see That inside Environment.java the client is trying to set threads as daemon threads and failing. So I turned on the security permissions in Glassfish policy file and the permission errors disappear. However since I am new to RabbitMQ I would like to ask if there is any recommended way to set permissions?  is anyone else using Rabbitmq client from inside an application server?

Thanks

/rajeev






Michael Klishin

unread,
Jan 30, 2015, 2:27:45 PM1/30/15
to Rajeev Jha, rabbitm...@googlegroups.com
 On 30 January 2015 at 22:13:07, Rajeev Jha (jha.r...@gmail.com) wrote:
> [2015-01-30T16:26:04.063+0000] [glassfish 4.0] [INFO]
> [] [javax.enterprise.system.core.security] [tid: _ThreadID=22
> _ThreadName=http-listener-1(5)] [timeMillis: 1422635164063]
> [levelValue: 800] [[
> 4745 JACC Policy Provider: Failed Permission Check, context(sensordb/sensordb)-
> permission(("java.lang.RuntimePermission" "modifyThread"))]]
>
>
> When examining rabbitmq client code, I could see That inside
> Environment.java the client is trying to set threads as daemon
> threads and failing. So I turned on the security permissions
> in Glassfish policy file and the permission errors disappear.
> However since I am new to RabbitMQ I would like to ask if there is
> any recommended way to set permissions? is anyone else using
> Rabbitmq client from inside an application server?

This is a solved problem since 3.3.0. See Custom Thread Factories on
http://www.rabbitmq.com/api-guide.html.
--
MK

Staff Software Engineer, Pivotal/RabbitMQ

Rajeev Jha

unread,
Feb 5, 2015, 2:33:53 PM2/5/15
to rabbitm...@googlegroups.com, jha.r...@gmail.com
Hi 

I have looked at the document and the only thing there is to set a CustomThreadFactory on connection factory. So I tried setting default managed thread factory of Java EE7 on rabbitmq connection factory.

@Resource(name = "concurrent/__defaultManagedThreadFactory")
ManagedThreadFactory threadFactory;
 ....
factory.setThreadFactory(threadFactory);


This seems to find the ThreadFactory but now it dies on line 36 of ConsumerWorkService
// NPE line
 this.executor = (executor == null) ? Executors.newFixedThreadPool(DEFAULT_NUM_THREADS, threadFactory) : executor;

2886 java.lang.NullPointerException
2887     at java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1312)
2888     at java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:1233)
2889     at java.util.concurrent.Executors.newFixedThreadPool(Executors.java:114)
2890     at com.rabbitmq.client.impl.ConsumerWorkService.<init>(ConsumerWorkService.java:36)

so clearly just setting ThreadFactory does not work and it needs an instance of ExecutorService also. is there any document for setting  clients inside Java EE7 environments? 


Thanks

Michael Klishin

unread,
Feb 5, 2015, 3:02:39 PM2/5/15
to Rajeev Jha, rabbitm...@googlegroups.com
 On 5 February 2015 at 22:33:55, Rajeev Jha (jha.r...@gmail.com) wrote:
> is there any document for setting clients inside Java EE7 environments?

There is no.

Rajeev Jha

unread,
Feb 16, 2015, 12:14:23 PM2/16/15
to rabbitm...@googlegroups.com, jha.r...@gmail.com
Hi Michael

Here are my observations of a Java EE7 environment (Glassfish v4.1 b12)

(1) Resource injection of ManagedThreadFactory or ManagedExecutorService is not working as desired in GlassFish V4.1 environment.  I have broken my head on this problem for quite some time but so far I have not been able to inject using @Resource. A simple servlet example works but not injection with my Jersey Jax-RS services. The NPE I was getting is beacuse of this

(2) looking up a managed thread factory or managed executor service via JNDI works.  Here is how I am receiving an executor service
                InitialContext ctx = new InitialContext();
       this.mes = (ManagedExecutorService) ctx.lookup("concurrent/rabbitmqes");

(3) The Rabbitmq API guide (https://www.rabbitmq.com/api-guide.html) says, "When the connection is closed a default ExecutorService will be shutdown(), but a user-suppliedExecutorService (like es above) will not be shutdown()" 

So I don't think it makes any sense to supply a managed Thread Factory with default executor service. in a managed Java EE7 environment, it may be better to supply a managed executor service that will not be touched by Rabbitmq implementation. The Google example in client docs may be specific to their environment but for java EE7 environments, a managed executor service should be recommended.

(4) The checkPermission method itself throws AccessDenied Exception in GlassFish container. 
sm.checkPermission(new RuntimePermission("modifyThread"));
(Access Denied Exception)

The only way to turn off the error is to grant permissions in server.policy file.

Thanks for your help

/rajeev

Michael Klishin

unread,
Feb 16, 2015, 12:17:16 PM2/16/15
to Rajeev Jha, rabbitm...@googlegroups.com
 On 16 February 2015 at 20:14:25, Rajeev Jha (jha.r...@gmail.com) wrote:
> The Google example in client docs may be specific to their environment
> but for java EE7 environments, a managed executor service should
> be recommended.

It's true that it was written with GCE in mind.

What should we recommend for JEE 7? (feel free to write a paragraph or two that we can use
as a base for a new section in the Java guide)

Thank you. 

Rajeev Jha

unread,
Mar 9, 2015, 6:31:14 AM3/9/15
to rabbitm...@googlegroups.com, jha.r...@gmail.com
Hi Michael
sorry for late reply. Here is what we have done with Glassfish V4.1. 


#rabbitmq producer inside Java EE7 environment


## Environment
The Java EE7 environment is Glassfish V4.1 open source edition.
$asadmin version 
prints "Version = GlassFish Server Open Source Edition  4.1  (build 13)"

## Requirement 
The problem is running a "producer" insider Glassfish V4.1 JVM, so whenever we  hit the application server from a web client, we send a message to rabbitmq server running on another machine.

web client (m1) -> Glassfish V4.1 + rabbitmq client (m2) -> rabbitmq server (m3)
m1 - machine 1
m2 - machine 2
m3 - machine 3


The web clients are hitting a service deployed with Jersey or you can use servlets. Since the  rabbitmq producer code is part of Glassfish V4.1 container, it is recommended to use a concurrent thread Executor service managed by the container. That way container is aware of threads  used by rabbitmq producer and there will be no *non-managed* threads running after container shutdown.

## Create managed executor service
To create a managed executor service in Glassfish V4.1, you can use Admin console or asadmin tool.
Glassfish comes in two flavors, web profile and java EE7 full platform.  Please download the full EE7 platform bundle.

To create a managed executor service named concurrent/rabbitmqes
$asadmin create-managed-executor-service --hungafterseconds=5 --corepoolsize=5 -concurrent/rabbitmqes

If web client processing by http thread and producing a message takes same amount of time then we can  configure  core pool size to be same as glassfish threadpool size. However this is not a fixed rule and  tune according to your situation.

## Use managed executor service

You can use managed executor service via resource injection or JNDI lookup. To use JNDI lookup inside your class,

InitialContext ctx = new InitialContext();
ManagedExecutorService mes = (ManagedExecutorService) ctx.lookup("concurrent/rabbitmqes");

An example class is

public class GFConcurrentUtil {
private static GFConcurrentUtil _instance = new GFConcurrentUtil();
private ManagedExecutorService mes = null;
private GFConcurrentUtil () {
try {
InitialContext ctx = new InitialContext();
       this.mes = (ManagedExecutorService) ctx.lookup("concurrent/rabbitmqes");
       
} catch(Exception ex) {
this.mes = null ;
Log.error(ex);
}
        
}
public static GFConcurrentUtil getInstance() {
return _instance ;
}
    public ManagedExecutorService getExecutorService() throws Exception {
    if(this.mes == null) {
    throw new Exception("error getting glassfish managed executor service");
    }
   
    return this.mes ;
    }
    

We make use of GFConcurrentUtil inside our rabbitmq producer class


        ConnectionFactory factory = new ConnectionFactory();
        ...
    factory.setHost(host);
   factory.setUsername(user);
   factory.setPassword(password);
   
   ManagedExecutorService mes = GFConcurrentUtil.getInstance().getExecutorService() ;
Connection connection = factory.newConnection(mes);
Channel channel = connection.createChannel();


## security exception and server.policy file

The rabbitmq producer class inside GFv4.1 will produce a security exception.
That is because Rabbitmq client will try to check security permissions, This line 

sm.checkPermission(new RuntimePermission("modifyThread"));

results in (Access Denied Exception)

To fix this issue, you need to add exceptions in GlassFish domain server.policy file


// rjha added for rabbitmq client
grant  {
    permission java.lang.RuntimePermission "modifyThread";
    permission java.lang.RuntimePermission "modifyThreadGroup";

} ;


## connection and channel usage pattern

channel design in rabbitmq is per thread so it is not good to share  a stateful channel between threads. we should create a channel on each web client hit. 

web client -> rabbitmq producer -> new channel -> write message -> close channel

connection represents an open socket to the rabbitmq machine and can be shared between two different web client requests. The number of channels created and closed in a time period will depend on the number of web requests served. The number of connections should be such that http threads should not be waiting for a rabbitmq connection.


## verification 

To verify is we are actually using managed executor service threads, we can attach JConsole to Glassfish  and verify the name of threads.

## future work

Use BTrace and verify that all calls to start a new Thread are using managed executor service.

## questions

(a) can rabbitmq connections be cached and shared?
(b) what methods inside the client call executor service?
(c) does rabbitmq shutdown sequence call a managed executor service shutdown?




 

Michael Klishin

unread,
Mar 9, 2015, 6:34:03 AM3/9/15
to Rajeev Jha, rabbitm...@googlegroups.com
  On 9 March 2015 at 13:31:17, Rajeev Jha (jha.r...@gmail.com) wrote:
> ## questions
> (a) can rabbitmq connections be cached and shared?

Yes but then you pretty much have to use automatic connection recovery.

> (b) what methods inside the client call executor service?

Consumer operations (basic.deliver, basic.consume-ok, etc) and server-sent
methods (channel.close, basic.cancel, connection.close, connection.[un]blocked).

> (c) does rabbitmq shutdown sequence call a managed executor
> service shutdown?

No, because the library can't know if something else may depend on it.

Rajeev Jha

unread,
Mar 9, 2015, 6:38:58 AM3/9/15
to Michael Klishin, rabbitm...@googlegroups.com
Hi Michael
so performance wise what are the recommendations around connections and channels? Create one each time you need one?

Thanks

/rajeev


Michael Klishin

unread,
Mar 9, 2015, 7:44:34 AM3/9/15
to Rajeev Jha, rabbitm...@googlegroups.com
On 9 March 2015 at 13:38:58, Rajeev Jha (jha.r...@gmail.com) wrote:
> so performance wise what are the recommendations around connections
> and channels? Create one each time you need one?

Opening a channel is a round-trip, so re-use channels when you know they will be long lived. 
Reply all
Reply to author
Forward
0 new messages