Статьи

Сервисная фабрика и OSGI Logging Предложение

В последнее время я размышлял о том, как мы можем регистрировать разные комплекты или один и тот же комплект с разными версиями с разным уровнем ведения журнала. Ведение журнала является важной частью любого приложения, поэтому Osgi предоставляет разработчикам logService для использования, когда это возможно, но стандартные API для ведения журналов (slf4j, log4j) просты в использовании.

Почему я
 задаю этот вопрос: 1 — Работа с osgi немного отличается в отношении простого программирования на Java: один и тот же класс может существовать во многих пакетах с разными версиями (разные загрузчики).
 2. Выполнение обновления некоторых комплектов путем изменения версий комплекта: мы должны оставить две работающие версии, если некоторые другие комплекты не обновлены для использования новой версии Milestone.

Я пытаюсь представить утилиты ServiceFactory и расскажу о возможном улучшении ведения журналов:

ServiceFactory:

мы создаем здесь три пакета:

1-logger: содержит api и impl
2-client 1: использование службы logger с версией 1 в качестве стабильной реализации уровень журнала — ОШИБКА
3 — клиент 2: используя службу регистрации с версией 2.0.0.m1 в качестве нестабильной реализации, уровень журнала — Отладка, чтобы перехватить все сообщения.

Вот черновик реализации класса logger:

package com.jtunisie.osgi.logger.impl;

import com.jtunisie.osgi.logger.Level;
import java.util.Dictionary;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.Version;

public class Logger implements com.jtunisie.osgi.logger.Logger, ServiceFactory {

@Override
public void log(Class clazz, Level level, String msg, Object... params) {
}

@Override
public Object getService(Bundle bundle, ServiceRegistration arg1) {

Dictionary dictionary = bundle.getHeaders();
Version version = Version.parseVersion((String)dictionary.get(org.osgi.framework.Constants.BUNDLE_VERSION));
String name = (String) dictionary.get(org.osgi.framework.Constants.BUNDLE_NAME);

com.jtunisie.osgi.logger.Logger logger = getLogger(name, version);
return logger;

}

private com.jtunisie.osgi.logger.Logger getLogger(String name, Version version) {
if (version.toString().contains("m")) {
return new ErrorLogger();
} else {
return new DebugLogger();

}
}

@Override
public void ungetService(Bundle arg0, ServiceRegistration arg1, Object arg2) {
}
}
package com.jtunisie.osgi.logger.impl;

import com.jtunisie.osgi.logger.Level;

class ErrorLogger implements com.jtunisie.osgi.logger.Logger {

@Override
public void log(Class clazz, Level level, String msg, Object... params) {
if (level.compareTo(Level.ERROR) == 0) {
msg = LoggerUtils.processMsg(params, msg);
System.out.println("----" +clazz+ " :>"+LoggerUtils.getMessage()+"//"+msg);
}

}
}
package com.jtunisie.osgi.logger.impl;

import com.jtunisie.osgi.logger.Level;

class DebugLogger implements com.jtunisie.osgi.logger.Logger{

@Override
public void log(Class clazz, Level level, String msg, Object... params) {
msg = LoggerUtils.processMsg(params, msg);
System.out.println("----" + clazz + " :>"+ LoggerUtils.getMessage()+"//"+msg);
}

}

клиент 1 и 2 относятся к простому классу активатора как

// клиент 1

package com.jtunisie.osgi.logger.client;

import com.jtunisie.osgi.logger.*;
import static com.jtunisie.osgi.logger.Level.*;

public class Activator {


private Logger logger;

public Activator(Logger logger) {
this.logger = logger;

}
public void init(){
logger.log(Activator.class ,DEBUG, "DEBUG : 1>>>>>My Id is ## version is ## ", 1,1);
logger.log(Activator.class ,ERROR, "ERROR : 1>>>>>My Id is ## version is ## ", 1,1);
}

}
package com.jtunisie.osgi.logger.client;

import com.jtunisie.osgi.logger.*;
import static com.jtunisie.osgi.logger.Level.*;

public class Activator {
private Logger logger;

public Activator(Logger logger) {
this.logger = logger;

}
public void init(){
logger.log(Activator.class ,DEBUG, "DEBUG : 2>>>>>My Id is ## version is ## ", 2,2);
logger.log(Activator.class ,ERROR, "ERROR : 2>>>>>My Id is ## version is ## ", 2,2);
}
}

если мы запустим эти примеры, результат будет выглядеть следующим образом:

—- класс com.jtunisie.osgi.logger.client.Activator:> Ср 08 окт. 03:25:18 CEST 2008 // ОШИБКА: 2 >>>>> Мой Идентификатор — 2 версия — 2
—- класс com.jtunisie.osgi.logger.client.Activator:> Ср 8 октября 03:25:18 CEST 2008 // ОТЛАДКА: 1 >>>>> Мой Идентификатор — 1 версия это 1
—- класс com.jtunisie.osgi.logger.client.Activator:> ср 08 окт. 03:25:18 CEST 2008 // ОШИБКА: 1 >>>>> Мой идентификатор — 1 версия, 1

==> ServiceFactory предоставляет новую реализацию для каждого клиента пакета в зависимости от его версии.

Предложение по

ведению журнала. При разработке osgi следует учитывать множество соображений: —

 Реализация класса может быть найдена в разных версиях пакетов с одинаковой версией пакета.
 Реализация класса может быть найдена в разных версиях пакетов с другой версией пакета.

log4j.dtd не имеет понятия связки и версии, и я предлагаю следующее:

 

<!ELEMENT log4j:configuration (renderer*, appender*,(category|logger)*,root?,
categoryFactory?)>

Will be

<!ELEMENT log4j:configuration (renderer*, appender*,(bundle|category|logger)*,root?,
categoryFactory?)>

и

мы добавляем версию в категорию и элемент logger,

чтобы наш файл log4j.xml мог быть:

<category name="com.jtunisie.osgi.logger.client">
<priority value="ERROR" version="[0.0.0,2.0.0("/>
<priority value="DEBUG" version="2.0.0"/>
</category>

or in our case

<bundle name="com.jtunisie.osgi.client">
<priority value="ERROR" version="[0.0.0,1.0.0("/>
<priority value="DEBUG" version="2.0.0"/>
</bundle>