wtorek, 1 lipca 2008

Log4J w 4 krokach

Nigdy więcej nie będę logować stanu aplikacji przez System.out.print :)
Ani też pisał własnych naiwnych implementacji loggerów.
Wszystko to dzięki Log4J, żeby go używać naprawdę potrzebujemy 4 kroków:

1. plik konfiguracyjny
Dzięki koledze Mariuszowi (Dzięki !)
dowiedziałem się, że wystarczy taki plik o nazwie np. config.properties

log4j.rootLogger=INFO,A1
log4j.appender.A1=org.apache.log4j.RollingFileAppender
log4j.appender.A1.File=log4j.log
log4j.appender.A1.MaxFileSize=1000KB
log4j.appender.A1.MaxBackupIndex=10
log4j.appender.A1.layout=org.apache.log4j.PatternLayout

# Print the date in ISO 8601 format
log4j.appender.A1.layout.ConversionPattern=\t%d [%t] %-5p %c%n%m%n


I teraz krótko co to znaczy:
log4j.rootLogger=INFO,A1
ustawia nam poziom logowania na 'INFO' a nazwę głównego loggera, do którego będziemy się dalej odnosić jako A1.
Dalej okreslamy nazwę pliku logów, jego maksymalny rozmiar, ilosć plików backupów do których jest kopiowana zawartosć logu po przekroczeniu maksymalnej wielkosci.
log4j.appender.A1.layout.ConversionPattern to magiczny wzorzec, który okrela co zostanie zapisane do pliku logów.

2. Sciągamy sobie log4j-1.2.15.jar i dodajemy do classpatha.
3. W metodzie main inicjalizujemy log4j używając do tego pliku config.properties:
public static void main(String[] argv) {
PropertyConfigurator.configure("log4j.properties");
........

4. W każdej klasie logującej inicjalizujemy logger dla nas
private static Logger logger = Logger.getLogger(MyLog4jExample.class);

I już można używać loggera w metodach klasy MyLog4jExample :)

logger.info("start loggera");

wtorek, 27 listopada 2007

Prywatne jak publiczne...

Czy można odczytać i nawet modyfikować w Javie zmienne prywatne?
Okazuje się, że tak...
Kluczem do tego jest mechanizm refleksji, który pozwala dobrać się do informacji o klasie i je zmodyfikować:

import java.lang.reflect.Field;

class FieldTest {
private String privateString = "Hello, World!";
}

public class privTest {

public static void main(String args[]) throws Exception {
FieldTest fieldTest = new FieldTest();

Field f = FieldTest.class.getDeclaredField("privateString");
System.out.println("Private Field: " + f);

f.setAccessible(true);
System.out.println(f.get(fieldTest));

f.set(fieldTest, "bulba");
System.out.println(f.get(fieldTest));
}

}


Co my tu mamy? Deklarujemy sobie klasę FieldTest z jednym prywatnym stringiem...
Właściwy kod jest w klasie privTest. Pobieramy obiekt reprezentujący informacje o polu 'privateString' a następnie zmieniamy je na dostępne przez setAccessible...
i już możemy robić z prywatną zmienną to co nam się podoba :)
Podobnie można zmodyfikować dostęp do konstruktorów i metod prywatnych.

Quartz c.d.

W poprzednim poście XML definiował mamy 4 powiązane ze sobą obiekty.
Zaczniemy od końca :)

1. Scheduler:
Jak można się domyślać, do zarządzania wszystkimi zdarzeniami potrzebujemy jednego z nich. Jest to obiekt 'scheduler' klasy org.springframework.scheduling.quartz.SchedulerFactoryBean. Tak więc dzięki temu, że w bibliotece Spring 2.0 mamy wsparcie dla Quartz możemy go tutaj wykorzystać.
Ponieważ chcemy, żeby zarządzanie zdarzeniami było włączone automatycznie po starcie aplikacji i czekało na zakończenie zadań przed zamknięciem, to ustawiamy atrybuty autoStartup i waitForJobsToCompleteOnShutdown na true.
Właciwosć 'triggers' tego obiektu służy do zdefiniowania samych zdarzeń.
U nas lista ta zawiera odwołanie tylko do jednego obiektu, dummyCronTrigger który jest zdefiniowany wyżej.

2. dummyCronTrigger - wyzwalacz zdarzenia.
Ponieważ chciałem, żeby zdarzenie było wywoływane co 10 sekund, musiałem użyć triggera bazującego na wyrażeniu polecenia Linuxowego cron.
W tym przypadku wygląda ono tak: 0/10 * * * * ?
Właściwość jobDetail ustawiamy na dummyJobDetail, czyli obiekt, który definiuje ma konkretne zadanie.

3. dummyJobDetails - służy tylko do wskazania metody obiektu, który wykona nasze zadanie.

4. outdatetProjectsMailSender to właściwy obiekt wykonujący nasze zadanie.
Przy implementacji zadania należy zwrócić uwagę, że ta metoda nie powinna rzucać wyjątków innych niż JobExecutionException.

Na koniec link do tutoriala, który przydał mi się do zrozumienia tego tematu:
http://www.lucianofiandesio.com/javatales/qtzfuse.html