В последнее время я размышлял о том, как мы можем регистрировать разные комплекты или один и тот же комплект с разными версиями с разным уровнем ведения журнала. Ведение журнала является важной частью любого приложения, поэтому 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>