Туториал: Как создать модуль для логгирования на стороне сервиса?

В этом посте нашей задачей будет получить SOAP сообщения на стороне сервиса. Для этого нам необходимо создать логгирующий модуль и подключить его к сервису.

Шаг 1. Создание проекта

Создаем проект Java Enterprise без библиотек и фреймворков, которые предлагает IDE. Импортируем axis2 библиотеку как описано в этом посте.

1

Шаг 2. Пишем код

Создаем главный класс, который имплементирует Module (по пути org.apache.axis2.modules). Добавьте все необходимые методы. Для этого вы можете нажать «Alt»+»Enter».

2

В итого содержимое классе будет по аналогии с этим:
public class Axis2GrabSOAPModule implements Module {
 @Override
 public void init(ConfigurationContext configurationContext, AxisModule axisModule) throws AxisFault {
 }
 @Override
 public void engageNotify(AxisDescription axisDescription) throws AxisFault {
 }
 @Override
 public boolean canSupportAssertion(Assertion assertion) {
  return false;
 }
 @Override
 public void applyPolicy(Policy policy, AxisDescription axisDescription) throws AxisFault {
 }
 @Override
 public void shutdown(ConfigurationContext configurationContext) throws AxisFault {
 }
}

Далее создаем класс, который наследуется от AbstractHandler и имплементирует Handler. Создаем необходимый метод invoke. Непосредственно в этой функции мы будем логгировать сообщения. Так же создадим метод init для указания файла для логгирования. Можно настроить Logger в TOMCAT_HOME/webapps/axis2/WEB-INF/classes, но я предпочитаю это делать через код. Итак, содержимое класса:

public class CustomHandler extends AbstractHandler implements Handler {
 private Logger log = Logger.getLogger(LogHandler.class);
 @Override
 public void init(HandlerDescription handlerdesc) {
  super.init(handlerdesc);
  SimpleLayout layout = new SimpleLayout();
  FileAppender appender = null;
  try {
   appender = new FileAppender(layout, "DESIRED_LOGFILE_PATH/log.txt", false);
  } catch (IOException e) {
   e.printStackTrace();
  }
  log.addAppender(appender);
 }
 @Override
 public InvocationResponse invoke(MessageContext messageContext) throws AxisFault {
  log.info(messageContext.getEnvelope().toString());
  return InvocationResponse.CONTINUE;
 }
}

Замените DESIRED_LOGFILE_PATH путем, где должен находится файл log.txt. Можно написать абсолютный адрес или относительный от TOMCAT_HOME/bin.

Шаг 3. Создаем/редактируем конфигурационные файлы.

Создаем папку «resources». Далее в нем создаем папку «META-INF». Создаем файл resources/META-INF/module.xml с содержимым, по аналогии с указанным ниже:

<module name="MyLoggingModule" class="Axis2GrabSOAPModule">
 <InFlow>
  <handler name="InFlowLogHandler" class="CustomHandler">
   <order phase="loggingPhase" />
  </handler>
 </InFlow>
 <OutFlow>
  <handler name="OutFlowLogHandler" class="CustomHandler">
   <order phase="loggingPhase"/>
  </handler>
 </OutFlow>
 <OutFaultFlow>
  <handler name="FaultOutFlowLogHandler" class="CustomHandler">
   <order phase="loggingPhase"/>
  </handler>
 </OutFaultFlow>
 <InFaultFlow>
  <handler name="FaultInFlowLogHandler" class="CustomHandler">
   <order phase="loggingPhase"/>
  </handler>
 </InFaultFlow>
</module>

Как вы можете видеть, создаваемый модуль будет логгировать сообщения в обоих направлениях (входящие и исходящие) и сообщения об ошибке.

Затем необходимо отредактировать файл axis2.xml, который находится по адресу TOMCAT_HOME/webapps/axis2/WEB-INF/conf. Здесь мы определяем когда должен отрабатывать наш модуль. Добавляем «<phase name=»loggingPhase»/>» внутри «<phaseOrder type=»inflow»>…</phaseOrder>», «<phaseOrder type=»outflow»>…</phaseOrder>», «<phaseOrder type=»INfaultflow»>…</phaseOrder>» и «<phaseOrder type=»Outfaultflow»>…</phaseOrder>». Привожу как пример часть моего axis2.xml файла:

 <phaseOrder type="InFlow">
  <!-- System predefined phases  -->
  <phase name="Transport">
   <handler name="RequestURIBasedDispatcher"
      class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher">
    <order phase="Transport"/>
   </handler>
   <handler name="SOAPActionBasedDispatcher"
      class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher">
    <order phase="Transport"/>
   </handler>
  </phase>
  <phase name="Addressing">
   <handler name="AddressingBasedDispatcher"
      class="org.apache.axis2.dispatchers.AddressingBasedDispatcher">
    <order phase="Addressing"/>
   </handler>
  </phase>
  <phase name="Security"/>
  <phase name="PreDispatch"/>
  <phase name="Dispatch" class="org.apache.axis2.engine.DispatchPhase">
   <handler name="RequestURIBasedDispatcher"
      class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher"/>
   <handler name="SOAPActionBasedDispatcher"
      class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher"/>
   <handler name="RequestURIOperationDispatcher"
      class="org.apache.axis2.dispatchers.RequestURIOperationDispatcher"/>
   <handler name="SOAPMessageBodyBasedDispatcher"
      class="org.apache.axis2.dispatchers.SOAPMessageBodyBasedDispatcher"/>
   <handler name="HTTPLocationBasedDispatcher"
      class="org.apache.axis2.dispatchers.HTTPLocationBasedDispatcher"/>
   <handler name="GenericProviderDispatcher"
      class="org.apache.axis2.jaxws.dispatchers.GenericProviderDispatcher"/>
   <handler name="MustUnderstandValidationDispatcher"
      class="org.apache.axis2.jaxws.dispatchers.MustUnderstandValidationDispatcher"/>
  </phase>
  <phase name="RMPhase"/>
  <!-- System predefined phases  -->
  <!-- After Postdispatch phase module author or service author can add any phase he want  -->
  <phase name="OperationInPhase">
   <handler name="MustUnderstandChecker"
      class="org.apache.axis2.jaxws.dispatchers.MustUnderstandChecker">
    <order phase="OperationInPhase"/>
   </handler>
  </phase>
  <phase name="soapmonitorPhase"/>
  <phase name="loggingPhase"/>
 </phaseOrder>
 <phaseOrder type="OutFlow">
  <!--  user can add his own phases to this area -->
  <phase name="soapmonitorPhase"/>
  <phase name="OperationOutPhase"/>
  <!--system predefined phase-->
  <!--these phase will run irrespective of the service-->
  <phase name="RMPhase"/>
  <phase name="PolicyDetermination"/>
  <phase name="MessageOut"/>
  <phase name="Security"/>
  <phase name="loggingPhase"/>
 </phaseOrder>
 <phaseOrder type="InFaultFlow">
  <phase name="Addressing">
   <handler name="AddressingBasedDispatcher"
      class="org.apache.axis2.dispatchers.AddressingBasedDispatcher">
    <order phase="Addressing"/>
   </handler>
  </phase>
  <phase name="Security"/>
  <phase name="PreDispatch"/>
  <phase name="Dispatch" class="org.apache.axis2.engine.DispatchPhase">
   <handler name="RequestURIBasedDispatcher"
      class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher"/>
   <handler name="SOAPActionBasedDispatcher"
      class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher"/>
   <handler name="RequestURIOperationDispatcher"
      class="org.apache.axis2.dispatchers.RequestURIOperationDispatcher"/>
   <handler name="SOAPMessageBodyBasedDispatcher"
      class="org.apache.axis2.dispatchers.SOAPMessageBodyBasedDispatcher"/>
   <handler name="HTTPLocationBasedDispatcher"
      class="org.apache.axis2.dispatchers.HTTPLocationBasedDispatcher"/>
   <handler name="GenericProviderDispatcher"
      class="org.apache.axis2.jaxws.dispatchers.GenericProviderDispatcher"/>
   <handler name="MustUnderstandValidationDispatcher"
      class="org.apache.axis2.jaxws.dispatchers.MustUnderstandValidationDispatcher"/>
  </phase>
  <phase name="RMPhase"/>
  <!--  user can add his own phases to this area -->
  <phase name="OperationInFaultPhase"/>
  <phase name="soapmonitorPhase"/>
  <phase name="loggingPhase"/>
 </phaseOrder>
 <phaseOrder type="OutFaultFlow">
  <!--  user can add his own phases to this area -->
  <phase name="soapmonitorPhase"/>
  <phase name="OperationOutFaultPhase"/>
  <phase name="RMPhase"/>
  <phase name="PolicyDetermination"/>
  <phase name="MessageOut"/>
  <phase name="Security"/>
  <phase name="loggingPhase"/>
 </phaseOrder>

Теперь нам необходимо отредактировать файл services.xml сервиса, который вы хотите логгировать. Я покажу на пример сервиса, созданного в данном посте:

 <service name="CustomService" scope="application" targetNamespace="http://doszhan.com/">
  <description>
   My Custom Service
  </description>
  <module ref="MyLoggingModule"/>
  <messageReceivers>
   <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" />
   <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
  </messageReceivers>
  <schema schemaNamespace="http://doszhan.com/xsd"/>
  <parameter name="ServiceClass">CustomService</parameter>
 </service>

Конечно после этого необходимо заново скомпилировать сервис. Для этого нужно проделать шаги 3 и 4 из поста.

Шаг 4. Сборка

Экспортируйте проект как jar. Для этого переходим «File»->»Project Structure…»->вкладка «Artifacts». Нажимаем на иконку зеленего плюса, выбираем «JAR»->»Empty». Задайте имя JAR-а. Нажимаем «Create Manifest…» и выбираем директорию resources/META-INF. Нажимаем иконку зеленого плюса из вкладки «Output Layout» и выбираем module.xml. В конце дважды кликаем «‘YOUR_PROJECT_NAME’ compile output» для добавления классов в модуль.

4

Нажимаем «OK» и запускаем сборку «Build»->»Build Artifacts…»->THE_NAME_OF_JAR->»Build». JAR файл должен создастся в папке «out». Переименуйте THE_NAME_OF_JAR.jar в THE_NAME_OF_JAR.mar. Ваш проект должен выглядеть по аналогии со следующим скриншотом:

4-2

Шаг 5. Запуск

Загружаем файл сервиса .aar в TOMCAT_HOME/webapps/axis2/WEB-INF/services. Загружаем файл модуля .mar в TOMCAT_HOME/webapps/axis2/WEB-INF/modules. Axis2 поддерживает «горячее» обновление сервиса, но не модуля. Поэтому в конце перезапускаем Tomcat.

После перезапуска можете проверить установилось ли все нормально. Для этого в браузере набираем «TOMCAT_SERVER_URL/manager/html». Введите логин и пароль. Логин и пароль настраиваются в файле tomcat-users.xml. Более подробно можете узнать в Шаге 1 посте. Переходит «/axis2″->»Administration». Входим в администраторскую панель Axis2. Стандартный логин/пароль: «admin/axis2». Проверьте страницы «Available Services» и «Available Modules».

Запускаем клиента сервиса и проверяем путь, который указали для файла log.txt. Если все работает нормально, то содержимое файла log.txt должно быть по аналогии с указанным ниже:
INFO - <?xml version='1.0' encoding='utf-8'?> <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"> <soapenv:Body> <ns2:getWorkerWithChangedSalary xmlns:ns2="http://doszhan.com/xsd"> <ns2:worker> <ns1:name xmlns:ns1="http://models/xsd">Doszhan </ns1:name> <ns1:position xmlns:ns1="http://models/xsd">specialist </ns1:position> <ns1:salary xmlns:ns1="http://models/xsd">100 </ns1:salary> <ns1:surname xmlns:ns1="http://models/xsd">Kalibek </ns1:surname> </ns2:worker> </ns2:getWorkerWithChangedSalary> </soapenv:Body> </soapenv:Envelope>
INFO - <?xml version='1.0' encoding='utf-8'?> <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"> <soapenv:Body> <ns:getWorkerWithChangedSalaryResponse xmlns:ns="http://doszhan.com/xsd"> <ns:return xmlns:ax21="http://models/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ax21:Worker"> <ax21:name>Doszhan </ax21:name> <ax21:position>specialist </ax21:position> <ax21:salary>200 </ax21:salary> <ax21:surname>Kalibek </ax21:surname> </ns:return> </ns:getWorkerWithChangedSalaryResponse> </soapenv:Body> </soapenv:Envelope>

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Картинка профиля Doszhan Kalibek

Doszhan Kalibek