Miesięczne archiwum: Październik 2012

Zdaj OCEWCD – pytanie 8

Co zostanie wydrukowane użytkownikowi po wykonaniu poniższego kodu servletu?
Należy założyć, że używamy Javy EE6.

@WebServlet("/Test")
public class TestServlet extends HttpServlet
{
    private static final String ATTR_NAME = "attr";

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        HttpSession session = request.getSession();
        session.setAttribute(ATTR_NAME, "val");

        session.setMaxInactiveInterval(0);

        Object obtained = session.getAttribute(ATTR_NAME);
        response.getWriter().println(obtained);
    }
}

 

  1. Wydrukowane zostanie ‚val’.
  2. Wydrukowane zostanie ‚null’.
  3. Kod nie skompiluje się.
  4. W trakcie wykonania rzucony zostanie wyjątek.
  5. Wydrukowane zostanie ‚attr’.

 

Pokaż odpowiedź »

Poprawna jest odpowiedź nr 1.

Linią komplikującą to pytanie jest z pewnością linia 11. Należy wiedzieć jakie znaczenie ma argument 0 w przypadku metody setMaxInactiveInterval. Jest to o tyle podchwytliwe, że w Javie EE5 cyfra 0 oznaczała natychmiastowe unieważnienie sesji. W przypadku powyższego kodu podczas pobierania atrybutu rzucony zostałby wyjątek IllegalStateException. Pytanie odnosi się jednak do Javy EE6, gdzie podobnie jak liczby ujemne, zero oznacza nieograniczony czas ważności sesji.

Zdaj OCEWCD – pytanie 7

Co zostanie wyświetlone użytkownikowi po wywołaniu servletu w następujący sposób?
http://host:port/context/Test?param=old

Należy założyć, że w miejsce host, port i context wstawione są poprawne wartości.

@WebServlet("/Test")
public class TestServlet extends HttpServlet
{
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        RequestDispatcher dispatcher = request.getRequestDispatcher("/Target?param=new");
        dispatcher.forward(request, response);
    }
}
@WebServlet("/Target")
public class TargetServlet extends HttpServlet
{
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        String first = request.getQueryString();
        String second = (String) request.getAttribute("javax.servlet.forward.query_string");

        response.getWriter().println(first + " " + second);
    }
}

 

  1. param=new null
  2. param=new param=old
  3. Kod nie skompiluje się.
  4. param=old param=old
  5. param=old null

 

Pokaż odpowiedź »

Poprawna jest odpowiedź nr 2.

W sytuacji, kiedy jeden servlet wywołuje drugi korzystając z metody forward w klasie RequestDispatcher, obiekt HttpServletRequest w docelowym servlecie zawiera już zaktualizowany query string - wartość przekazaną przy okazji wywołania metody getRequestDispatcher(). Jest jednak możliwość dostania się do oryginału – wystarczy odczytać wartość atrybutu żądania o nazwie javax.servlet.forward.query_string. Istnieją również analogiczne atrybuty dla innych kluczowych wartości przechowywanych w obiekcie żądania:

  • javax.servlet.forward.request_uri 
  • javax.servlet.forward.context_path 
  • javax.servlet.forward.servlet_path 
  • javax.servlet.forward.path_info
Odpowiadają kolejno rezultatom wywołania metod getRequestURI, getContextPath, getServletPath, oraz getPathInfo klasy HttpServletRequest.

Zdaj OCEWCD – pytanie 6

Co zostanie wydrukowane po starcie aplikacji zawierającej poniższy deskryptor wdrożenia oraz klasy?

<web-app ...>
    <listener>
        <listener-class>
            eu.javablog.ocewcd.SecondContextListener
  	</listener-class>
    </listener>
    <listener>
        <listener-class>
            eu.javablog.ocewcd.FirstContextListener
        </listener-class>
    </listener>
</web-app>
public class FirstContextListener implements ServletContextListener
{
    @Override
    public void contextDestroyed(ServletContextEvent arg0)
    {

    }

    @Override
    public void contextInitialized(ServletContextEvent arg0)
    {
        System.out.println("FIRST");
    }
}
public class SecondContextListener implements ServletContextListener
{
    @Override
    public void contextDestroyed(ServletContextEvent arg0)
    {

    }

    @Override
    public void contextInitialized(ServletContextEvent arg0)
    {
        System.out.println("SECOND");
    }
}

 

  1. Nic nie zostanie wydrukowane.
  2. Wydrukowane zostanie odpowiednio FIRST i SECOND.
  3. Kolejność wydruku zależy od implementacji kontenera.
  4. Wydrukowane zostanie odpowiednio SECOND i FIRST.
  5. Kod nie skompiluje się.

 

Pokaż odpowiedź »

Poprawna jest odpowiedź nr 4.

Kolejność wykonania listenerów jest zgodna z kolejnością ich deklaracji w deskryptorze wdrożenia. Jest to zachowanie gwarantowane, opisane w specyfikacji.

TechCamp – sezon drugi

Prawie rok temu wystartował pierwszy sezon TechCampu. Jeżeli zapoznaliście się z naszą relacją z pierwszego, inauguracyjnego spotkania, pewnie wiecie już, że TechCamp jest inicjatywą, w której warto uczestniczyć i którą warto wspierać. Miło nam zatem poinformować, że javablog.eu został oficjalnym patronem drugiej edycji. Czytaj dalej

Java Runs Really Fast!

Z tytułem tego wpisu chyba wszyscy się zgadzamy, prawda? :) Podobnego zdania są też specjaliści z EPAM Systems, którzy przy współpracy z Katedrą Informatyki Akademii Górniczo-Hutniczej w Krakowie postanowili zorganizować cykl bezpłatnych wykładów przybliżających metody radzenia sobie z popularnymi problemami z wydajnością aplikacji opartych o język Java. Cykl składać się będzie z trzech wykładów, na których omawiane będą m.in. takie zagadnienia jak: systemy NoSQL, Java Memory Model, programowanie wielowątkowe oraz działanie Garbage Collectora. Co ciekawe, zwieńczeniem cyklu wykładów będzie konkurs programowania w parach. Czytaj dalej

Zdaj OCEWCD – pytanie 5

Co zostanie wydrukowane po skompilowaniu i uruchomieniu poniższego servletu?

@WebListener
public class RequestAttributeListener implements ServletRequestAttributeListener
{
    @Override
    public void attributeAdded(ServletRequestAttributeEvent e)
    {
        System.out.println("ADDED:" + e.getValue());
    }

    @Override
    public void attributeRemoved(ServletRequestAttributeEvent e)
    {
        System.out.println("REMOVED:" + e.getValue());
    }

    @Override
    public void attributeReplaced(ServletRequestAttributeEvent e)
    {
        System.out.println("REPLACED:" + e.getValue());
    }
}
@WebServlet("/Test")
public class TestServlet extends HttpServlet
{
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        request.setAttribute("attr", "1");
        request.setAttribute("attr", "2");
        request.removeAttribute("attr");
    }
}

 

  1. ADDED:1 REPLACED:2 REMOVED:null
  2. ADDED:1 REPLACED:1 REMOVED:null
  3. ADDED:1 REPLACED:2 REMOVED:
  4. ADDED:1 REPLACED:1 REMOVED:2
  5. ADDED:1 REPLACED:2 REMOVED:2

 

Pokaż odpowiedź »

Poprawna jest odpowiedź nr 4.

Przeanalizujmy po kolei wartości dostępne w listenerze dla kolejnych etapów życia atrybutu. W przypadku dodania zachowanie jest chyba logiczne – otrzymujemy dokładnie taką wartość, jaką mu nadaliśmy. Sprawy nieco się komplikują przy nadpisaniu atrybutu. Logika podpowiada, że powinniśmy dostać nową wartość. Tak jednak się nie dzieje – uzyskujemy dostęp do wartości starej, która to została nadpisana. W momencie kiedy usuwamy atrybut, wartość dostępna dla listenera to ostatnia wartość usuwanego atrybutu.

Warsjawa 2012

Jeżeli uważacie, że na tradycyjnych konferencjach jest zdecydowanie za dużo teorii, a za mało przykładów praktycznego zastosowania omawianych tematów, to powinniście odwiedzić Warszawę w dniu 27 października. To właśnie wtedy odbywać się będzie kolejna edycja konferencji Warsjawa, która będzie wolna od nudnych i teoretycznych wystąpień. Przez cały dzień będzie można uczestniczyć w warsztatach, których tematyka prezentuje się bardzo ciekawie:

  • Injektowanie zależności w GUICE + zdalne injektowanie – Paweł Cesar Sanjuan Szklarz
  • Jenkins and Continous Delivery – Marcin Sawicki i Andrzej Grzesik
  • JAVA + Elektronika – Przemysław Lewandowski
  • iOS: Kickstart – Antoni Kędracki
  • Qooxdoo – Tomek Kuprowski
  • Narzędzia zwinnego modelowania wymagań: BDD i Specification by Example – Sławomir Sobóka & Rafał Jamróz
  • Liferay jako bezpieczny framework Javowy – Mateusz Hyski
  • Jeden dzień z trudnym klientem – zwinny projekt w formie gry – Ola Puchta i Tomek Szymański and others
  • Czemu Groovy jest spoko, a Spock jest groovy? – Tomek Przybysz i Artur Gajowy
  • Git, Gerrit i audyt kodu w praktyce

Śpieszcie się z rejestracją! Organizatorzy uprzedzają, że o uczestnictwie w warsztatach będzie decydowała kolejność zgłoszeń.

Zdaj OCEWCD – pytanie 4

Jaki będzie efekt skompilowania i uruchomienia przedstawionego poniżej kodu servletu?

@WebServlet("/Test")
public class TestServlet extends HttpServlet
{
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        PrintWriter writer = response.getWriter();
        writer.println("Please wait, redirecting...");
        writer.flush();

        response.sendRedirect("http://www.javablog.eu");
    }
}

 

  1. Użytkownik zobaczy informację, po czym będzie przekierowany na javablog.eu.
  2. Użytkownik zobaczy pustą stronę, ponieważ rzucony zostanie wyjątek.
  3. Użytkownik zobaczy informację, po czym rzucony zostanie wyjątek.
  4. Kod nie skompiluje się.
  5. Użytkownik od razu zostanie przekierowany na stronę javablog.eu.

 

Pokaż odpowiedź »

Poprawna jest odpowiedź nr 3.

W linii siódmej piszemy do obiektu odpowiedzi, po czym w linii ósmej ją ‚zatwierdzamy’. W tym momencie response jest odsyłany do klienta, i nie jesteśmy już w stanie nic w nim zmienić. Próbujemy jednak tego w kolejnej linii – chcemy przekierować użytkownika na stronę javablog.eu. Kontener informuje nas o naszej pomyłce następującym wyjątkiem: java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed.

Zdaj OCEWCD – pytanie 3

Jaki będzie efekt działania przedstawionego poniżej kodu? Na potrzeby pytania załóżmy, że plik test.jsp istnieje i znajduje się na równi z katalogiem WEB-INF.

@WebServlet("/Test")
public class TestServlet extends HttpServlet
{
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        request.setAttribute("text", "Hello!");
        getServletContext().getRequestDispatcher("test.jsp").forward(request, response);
    }
}

 

  1. Kod nie skompiluje się, ponieważ ServletContext nie ma takiej metody.
  2. Użytkownik zostanie prawidłowo przekierowany na stronę test.jsp.
  3. Rzucony zostanie IllegalArgumentException.
  4. Kod nie skompiluje się, ponieważ metoda forward() ma inną sygnaturę.
  5. Kod nie skompiluje się, ponieważ metoda getRequestDispatcher() nie przyjmuje żadnych parametrów.

 

Pokaż odpowiedź »

Poprawna jest odpowiedź nr 3.

Powodem rzucenia takiego wyjątku jest niepoprawny argument przekazany metodzie getRequestDispatcher(). Co ciekawe, jeśli pozyskalibyśmy request dispatcher z obiektu request, kod działałby poprawnie. Dzieje się tak dlatego, iż ServletContext wymaga użycia ścieżki bezwzględnej przy wywołaniu metody getRequestDispatcher() (musi ona zaczynać się od znaku ‚/’). Inaczej jest w przypadku używania instancji HttpServletRequest – tutaj możliwe jest podanie ścieżki względem tej aktualnej. W ramach testu polecam podmienić linię 7 na poniższą:


request.getRequestDispatcher("test.jsp").forward(request, response);

Zdaj OCEWCD – pytanie 2

Poniżej znajduje się listing przedstawiający deskryptor wdrożenia (deployment descriptor) oraz kod servletu. Które z przedstawionych linii kodu wstawione w oznaczone miejsce pozwolą pobrać wartość parametru param_name? Tag <web-app> został celowo skrócony. Na potrzeby pytania należy założyć, że jest kompletny i poprawny.

<web-app ... >
   <context-param>
      <param-name>param_name</param-name>
      <param-value>some_value</param-value>
   </context-param>
</web-app>
@WebServlet("/Test")
public class TestServlet extends HttpServlet
{
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        // insert code to read parameter value here
    }
}

 

  1. Nie jest to możliwe.
  2. getServletConfig().getServletContext().getInitParameter(„param_name”);
  3. getServletConfig().getInitParameter(„param_name”);
  4. getServletContext().getInitParameter(„param_name”);
  5. getServletContext().getContextParameter(„param_name”);

 

Pokaż odpowiedź »

Poprawne są odpowiedzi 2 oraz 4.

Po pierwsze należy pamiętać o tym, że parametry definiowane przy użyciu tagu
<context-param> są, jak sama nazwa mówi, parametrami całego kontekstu aplikacji. Dostęp do nich można więc uzyskać poprzez ServletContext, a nie ServletConfig, który to jest tworzony dla każdego servletu z osobna. Służy do tego metoda getInitParameter(). Kolejną ważną kwestią są sposoby uzyskania dostępu do samego obiektu ServletContext. Wewnątrz servletu mamy dwa wyjścia – możemy wywołać bezpośrednio metodę getServletContext(), albo użyć dłuższego ciągu wywołań: getServletConfig().getServletContext(). Obydwie formy są poprawne.