Jak dodać dane do Interceptora?

0

Hej, próbuję do logów dorzucić dane z Interceptora, ale nie chce działać. Czy ktoś mógłby mnie naprowadzić na co zwrócić uwagę?

Moje klasy Interceptora:

@Inherited
@InterceptorBinding
@Retention(RUNTIME)
@Target({ METHOD, TYPE })
public @interface MdcInterceptorBinding {
}

druga klasa:

@Interceptor
@MdcInterceptorBinding
public class MdcInterceptor {

    private final static String MDC_PROCESS_IUV_KEY = "mdc.process.iuv.key";

    @AroundInvoke
    public Object log(InvocationContext context) throws Exception {
        System.out.println("INTERCEPTOR LOG "+ context.getMethod().getName());
        try {
            MDC.put( MDC_PROCESS_IUV_KEY, UUID.randomUUID().toString().replaceAll("-",""));
            return context.proceed();
        }
        finally {
            MDC.remove(MDC_PROCESS_IUV_KEY);
        }
    }
}

mój pattern w logback.xml:

<property name="layout_pattern" value="%d{HH:mm:ss.SSS}-%X{mdc.process.iuv.key:-n/a}-[%thread]-%-5level-%logger{36}-%n%msg%n"/>

Nad metodą, którą chcę łapać wrzuciłam adnotację @MdcInterceptorBinding.

No i jeszcze moje pom.xml:

<dependency>
  <groupId>jakarta.interceptor</groupId>
  <artifactId>jakarta.interceptor-api</artifactId>
  <version>2.2.0-RC1</version>
</dependency>

Nie działa tak jak powinno, drukuje n/a. A tego loga nawet nie drukuje: System.out.println("INTERCEPTOR LOG "+ context.getMethod().getName());

Ktoś jest w stanie mnie naprowadzić co tu jest źle?

Pozdrawiam :)

2

A dlaczego miałby ten interceptor w ogóle zadziałać?
Pokaż jak wygląda metoda z adnotacją. Skąd się biorą obiekty z tą metodą?
Spring?

0

A zatem, metoda z adnotacją:

@MdcInterceptorBinding
public void process (FoundIuv foundIuv) throws Exception{
    try {
        Optional<PagamentoStor> pagamentoStorOpt = selector.selectPagamento(foundIuv.getIuv());
        if (pagamentoStorOpt.isPresent()) {
            addInsertBatch(pagamentoStorOpt.get(), foundIuv);
        } else {
            foundIuv.setError("Not found");
        }
    } catch (SelectorI.DuplicateIdDebitoException e) {
        foundIuv.setError("Duplicated id_debito: " + e.getIdDebito());
    }
}

Użycie metody:

public List<FoundIuv> reactivate(List<String> iuvList) throws Exception {
     List<FoundIuv> foundIuvList = new ArrayList<>();
     FoundIuv foundIuv;
     for (String iuv : iuvList) {
         foundIuv = new FoundIuv(iuv);
         process(foundIuv);
         foundIuvList.add(foundIuv);
     }
     executeBatch();
     return foundIuvList;
 }

Metodę tę na razie tylko testowałam z mockito, tworząc obiekt w ten sposób:

private ReactivatorI getReactivatorV2() throws SQLException {
    Connection con = mock(Connection.class);
    doNothing().when(con).commit();
    doNothing().when(con).rollback();
    return new ReactivatorV2(con, idCompany, selector, infoAggBatchRepo, phBatchRepo, rptBatchRepo);
}

i w teście docelowym:

List<FoundIuv> foundIuvList = reactivator.reactivate( dataFromDbList.stream().map(DataFromDb::getIuv).collect(Collectors.toList()) );

Ogólnie to kolega z pracy zaczął robić ten interceptor, ale nie działało. To jest projekt bez Springa. Szukam teraz jak to dokończyć.

PS. Jestem na stażu od paru miesięcy, jeszcze nie ogarniam takich rzeczy.

1

Wydaje się, że masz już dobrze skonfigurowany Interceptor w swojej aplikacji, ale problem może wynikać z faktu, że używasz adnotacji @Inherited na swoim @InterceptorBinding (MdcInterceptorBinding).

Adnotacja @Inherited informuje Javę, że adnotacja danego typu może być dziedziczona przez podklasy, ale w przypadku adnotacji @InterceptorBinding nie jest to konieczne, ponieważ InterceptorBinding nie jest typem, który jest dziedziczony przez klasy, ale raczej jest stosowany do metod lub klas, które mają być przechwytywane przez Interceptory.

Z tego powodu, próba użycia @Inherited w @InterceptorBinding może prowadzić do nieoczekiwanych wyników, ponieważ adnotacje stosowane do interfejsów nie są dziedziczone przez klasy implementujące ten interfejs.

Aby rozwiązać ten problem, po prostu usuń adnotację @Inherited z @InterceptorBinding, a Twoje adnotacje powinny działać zgodnie z oczekiwaniami. Po zmianie tej konfiguracji, sprawdź, czy Twoje Interceptory są wywoływane jak oczekiwano.

1

Czyli jasne - to po prostu nie będzie działać.
Koniec.

Normalnie w javie nie ma żadnej magii, która by powodowała, że będą działać interceptory itp. badziewia.

Takie cuda są tylko możliwe jeśli odpalasz projekt ze springiem, javaee - kontenerem. (A może masz jakieś javaEE - jboss?)

Co więcej wymaga to dodatkowych ograniczeń - obiekt na którym interceptory działają musi być utworzony przez kontener (w twoich testach na pewno nie jest). Co więcej jak masz metodę z adnotacją to wywołanie jest z innej metody tej samej klasy nie spowoduje zadziałania interceptora (zwykle).

Tak, to porypane i problematyczne - ja się w to nie bawię.

Czy Twoje zadanie to "zrób interceptor", czy może jakieś inne, a interceptor Ci przyszedł do głowy?

1

Hej, może ktoś będzie mieć podobny problem więc tylko dopiszę, że w końcu udało mi się użyć Interceptora bez Springa i CDI. Użyłam obiektu proxy. Celem było stworzenie unikalnego numeru dla każdej procesowanej płatności, ale bez wchodzenia z MDC bezpośrednio do środka kodu metody. Zadziałało coś takiego:

interface Target {
    void doSomething();
}

class TargetImpl implements Target {
    public void doSomething() {
        System.out.println("Doing something...");
    }
}

class Interceptor implements InvocationHandler {
    private final Object target;

    public Interceptor(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      System.out.println("Before method invocation");
      Object result = method.invoke(target, args);
      System.out.println("After method invocation");
      return result;
    }
}

public class Main {
    public static void main(String[] args) {
        Target target = new TargetImpl();

        Target proxy = (Target) Proxy.newProxyInstance(
                Target.class.getClassLoader(),
                new Class[]{Target.class},
                new Interceptor(target));

        proxy.doSomething();  
    }
}

A to już moja gotowa klasa Interceptora:

public class MdcInterceptor implements InvocationHandler {

    private final String MDC_PROCESS_IUV_KEY = "mdc.process.iuv.key";
    private final Object target;
    private static Logger log = LoggerFactory.getLogger(MdcInterceptor.class);

    public MdcInterceptor(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if(method.getName().equals("process")) {
            try {
                MDC.put(MDC_PROCESS_IUV_KEY, UUID.randomUUID().toString().replaceAll("-", ""));
                return method.invoke(target, args);
            } finally {
                MDC.remove(MDC_PROCESS_IUV_KEY);
            }
        } else {
            return method.invoke(target, args);
        }
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1