style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Problemas con FileHandler concurrente

La descripción de mi problema es la siguiente:

Tengo desarrollados algunos plugins de Oracle Access Manager, cada plugin utiliza una instancia del Logger de OAM (Ya viene en la API), cada plugin deberá escribir su información hacia un archivo por lo cual utilice la clase FileHandler y se la agregue al Logger, pero tenia el problema de que creaba muchos archivos (más de los que le ponia en el parametro de archivos a rotar que era de 5) porque generaba archivos .lck mientras atendia otro plugin debido a que la concurrencia de llamadas a los plugins era muy alta, esto lo solucione utilizando un singleton de la clase FileHandler pero debido a que el metodo estático para obtener el Singleton esta sincronizado generá algunas excepciones de timeouts supongo porque va encolando las peticiones hacia el FileHandler, como podría solucionarlo ?

Dejo la emulación del plugin y una prueba standalone de como se comportaría mi código:

//Codigo del plugin
import java.util.Collections;
import java.util.Map;
import java.util.logging.Level;
import oracle.security.am.plugin.ExecutionStatus;
import oracle.security.am.plugin.MonitoringData;
import oracle.security.am.plugin.PluginConfig;
import oracle.security.am.plugin.authn.AbstractAuthenticationPlugIn;
import oracle.security.am.plugin.authn.AuthenticationContext;
import oracle.security.am.plugin.authn.AuthenticationException;

public class FakePlugin extends AbstractAuthenticationPlugIn {

        public ExecutionStatus initialize(PluginConfig config) {
                try
                {
                        LOGGER.addHandler(SingletonFileHandler.getSingletonFileHandler("/asdk/loggs.log", 10240, 5).getFile());
                        LOGGER.setLevel(Level.ALL);
                } catch (Exception e)
                {
                        LOGGER.log(Level.INFO, e.getMessage());
                        e.printStackTrace();
                }

                return ExecutionStatus.SUCCESS;
        }

        @Override
        public ExecutionStatus process(AuthenticationContext ac) throws AuthenticationException {

                LOGGER.log(Level.INFO, "Ejecutando process() " + this.getPluginName() + " " + Thread.currentThread().getName());
                return ExecutionStatus.SUCCESS;
        }

        public ExecutionStatus shutdown() {
                LOGGER.log(Level.INFO, "Plugin Terminado");
                return ExecutionStatus.SUCCESS;
        }

        @Override
        public String getDescription() {
                return "Fake";
        }

        @Override
        public Map <String, MonitoringData> getMonitoringData() {
                return Collections.emptyMap();
        }

        @Override
        public boolean getMonitoringStatus() {
                return false;
        }

        @Override
        public String getPluginName() {
                return this.getClass().getSimpleName();
        }

        @Override
        public int getRevision() {
                return 1;
        }

        @Override
        public void setMonitoringStatus(boolean bln) {

        }

}

//Codigo del Singleton
import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.SimpleFormatter;

public class SingletonFileHandler extends FileHandler {

        private static FileHandler fileHandler;
        private static SingletonFileHandler singleton;

        private SingletonFileHandler(String path, int size, int files) throws IOException {
                fileHandler = new FileHandler(path, size, files, true);
                fileHandler.setFormatter(new SimpleFormatter());
        }

        public static synchronized SingletonFileHandler getSingletonFileHandler(String path, int size, int files) throws IOException {
                if (singleton == null)
                {
                        singleton = new SingletonFileHandler(path, size, files);
                }
                return singleton;
        }

        public FileHandler getFile() {
                return fileHandler;
        }
}

/*Con esta clase trato de emular 500 llamados al plugin pero obviamente aqui no obtendre los timeouts o excepciones que pueda generar en su ambiente productivo con OAM*/
public class Test {

        public static void main(String[] args) {

                for (int i = 0; i < 500; i++)
                {
                        new Thread(new Runnable() {

                                public void run() {
                                        FakePlugin plug = new FakePlugin();
                                        plug.initialize(null);
                                        try
                                        {
                                                Thread.sleep(1);
                                        } catch (InterruptedException ex)
                                        {
                                                ex.printStackTrace();
                                        }
                                        plug.process(null);
                                        plug.shutdown();
                                }
                        }).start();
                }
        }
}

De antemano muchas gracias por su opinion y ayuda.

Saludos.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

antipatrón

Esto es un buen ejemplo de un antipatrón. Cuándo NO se debe usar un singleton.

Imagen de Cid

Ok pero como hago que cada

Ok pero como hago que cada plugin pueda loggear a un archivo diferente sin que se crucen, y por supuesto sin singleton ? ....
...
Ya lo he intentado con el logger de Java pero al tener llamadas concurrentes genera muchos archivos .lck y genera más archivos de los que le indico que debe de rotar precisamente porque mientras atiende una petición puede dejar a medias otra (por aquello de la concurrencia) con un archivo .lck y genera uno nuevo.

¿Programáticamente?

 

¿Y por qué hacerlo programáticamente? ¿Has intentado el procedimiento que se describe en https://docs.oracle.com/cd/E28280_01/dev.1111/e12491/authnapi.htm#AIDEV259 ?

java.util.logging normalmente se configura a través de su archivo logging.properties, único para cada JVM (1). Tomcat también lo utiliza, aunque ha agregado algunas clases para permitir que cada contexto pueda tener su propio logging.properties. Y en el caso de OAM, este utiliza el archivo logging.xml. (2)


Notas

  1. Si no se especifica alguno a través de la propiedad java.util.logging.config.file, se utiliza uno por defecto que, en Windows, se localiza, ya sea en «C:\Program Files\Java\jre1.8.0_25\lib\logging.properties» o ya sea en «C:\Program Files\Java\jdk1.8.0_25\jre\lib\logging.properties». Dependerá del JRE que se esté utilizando.
  2. https://docs.oracle.com/cd/E27559_01/admin.1112/e27239/logging.htm#AIAAG...

~~~

Imagen de Cid

Eso se lo dije a mi jefe y no hizo caso

Jajaja curiosamente eso ya lo había leido pero mi jefe insistio en hacerlo programáticamente le mostrare este link a ver si ahora si hace caso, muchas gracias @jpaul.

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">