EJB wewnątrz drugiego EJB w tym samym projekcie

0

Witam,
mam takie dość ciekawe zadanie do wykonania. Mianowicie:

  • Mam jednego EJB opisanego interfejsem (więc go nie da rady ruszyć) - inicjuje grę i sprawdza czy podany wynik jest poprawny
  • Mam drugiego EJB, który powinien wykonać algorytm rozwiązania gry MasterMind dla 5 kolumn i 8 kolorów.
  • Mam servlet, który inicjuje grę (przez pierwszy EJB) po czym ją uruchamia (drugi EJB) i zwraca wynik.

Problem jest taki, że do wykonania algorytmu (algorytm Knutha), potrzebuje wiedzy: ile kulek było ułożonych dobrze oraz ile kolorów się pokryło. Tą wiedzę oferuje pierwszy EJB. Problemem jest - co zrobić żeby móc z niego korzystać?

Podanie go przez setera czy zrobienie z niego publicznego argumentu odpada, bo nie zgadza się na to interfejs (mam wymuszone, że ma się składać z jednej bez argumentowej metody - więc zrobienie funkcji rekurencyjnej też odpada). EJB nie może mieć też konstruktora z argumentami, więc i ta metoda odpada.

Po prostu jeden EJB musi jakoś znaleźć drugi. Oba są w jednym projekcie w jednej paczce.

Jeżeli może to pomóc, to rzucam kod:

Pierwszy EJB (GameMonitor) - tutaj jest bardzo przykładowy, bo przy ostatecznym rozwiązaniu ten skrypt zostanie podany odgórnie, stąd nie mam na niego w ogóle wpływu.

package game;

import java.util.Arrays;
import javax.ejb.Stateful;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@Stateful
public class GameMonitor implements IGameMonitor{
    
    private String goodCombination;
    
    @Override
    public boolean register(int hwork, String album) {
        try {
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public void initGame(String state) {
        goodCombination = state;
    }

    @Override
    public String verify(String state) {
        
        int colorOK = 0;
        int allOK = 0;
        
        char[] st = state.toCharArray();
        char[] gc = goodCombination.toCharArray();
        
        for(int i = 0 ; i < 5 ; i++) {
            if(st[i] == gc[i]) {
                allOK++;
                continue;
            }
            
            if(Arrays.asList(gc).contains(st[i])) {
                colorOK++;
            }
        }
        
        String result  = allOK + "" + colorOK;
        
        return result;
    }
}

Drugi EJB (MasterMind) ktory wykonuję samą grę. W nim potrzebuje poprzedniego EJB, ale nie mogę go zaimportować. Próbowałem już na masę różnych sposobów. Ten zaprezentowany tutaj, powoduje NullPointer.

package game;

import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.ejb.SessionContext;
import javax.ejb.Stateful;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.PersistenceContext;

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@Stateful
public class MasterMind implements IMasterMind{
    
    @Override
    public String playGame() {
        int steps = 0;
        
        try {
            String attempt = "AABBB";
            ArrayList<String> possibleGuess = createPossibleGuessArray("", "ABCDEFGH");
            ArrayList<String> bestGuess = new ArrayList<String>();
            String result = "00";
            
            //Context context = new InitialContext();
            //IGameMonitor gameMonitor = (IGameMonitor) context.lookup("java:global/ejb-project/IGameMonitor!pl.jrj.game.IGameMonitor");
            IGameMonitor gameMonitor = (IGameMonitor) context.lookup(IGameMonitor.class.getName());
                        
            do {
                if(steps == 0) {
                    // Pierwsza proba
                    attempt = "AABBB";
                } else if(possibleGuess.size() == 1) {
                    // Ostatnia opcja
                    attempt = possibleGuess.get(0);
                } else {
                    // usuwamy z tablicy poprzedni strzal
                    possibleGuess.remove(attempt);
                    ArrayList<Integer> tmpRemoveList = new ArrayList<>();
                    
                    // usuwamy wszystkie, ktore dalyby podobny rezultat
                    for(int i = 0 ; i < possibleGuess.size() ; i++) {
                        int goodPin = 0;
                        int goodColor = 0;
                        
                        for(int pin = 0 ; pin < 5 ; pin++) {
                            if(possibleGuess.get(i).charAt(pin) == attempt.charAt(pin)) {
                                goodPin++;
                            } else if(possibleGuess.get(i).contains("" + attempt.charAt(pin))) {
                                goodColor++;
                            }
                        }
                        
                        if(goodPin != result.charAt(0) && goodColor != result.charAt(1)) {
                            tmpRemoveList.add(i);
                        }
                    }
                    
                    for(int i : tmpRemoveList) {
                        possibleGuess.remove(i);
                    }
                    
                    // Wybireamy kolejny krok, szukajac opcji, ktora wyeliminuje najwiecej opcji
                    int maxMin = 0;
                    for(int i = 0 ; i < possibleGuess.size() ; i++) {
                        int min = Integer.MAX_VALUE;
                        int goodPin = 0;
                        int goodColor = 0;
                        for(int pin = 0 ; pin < 5 ; pin++) {
                            if(possibleGuess.get(i).charAt(pin) == attempt.charAt(pin)) {
                                goodPin++;
                            } else if(possibleGuess.get(i).contains("" + attempt.charAt(pin))) {
                                goodColor++;
                            }  
                        }
                        if(goodPin != result.charAt(0) && goodColor != result.charAt(1)) {
                            min++;
                        }
                        
                        if(min == maxMin && min > 0) {
                            bestGuess.add(possibleGuess.get(i));
                        }
                        
                        if(min > maxMin) {
                            maxMin = min;
                            bestGuess.clear();
                            bestGuess.add(possibleGuess.get(i));
                        }
                    }
                    
                    attempt = bestGuess.get(0);
                } 
                
                result = gameMonitor.verify(attempt);
                steps++;
            } while (!result.equals("50"));
            
            
        //} catch (NamingException ex) {
          //  return ex + " - " + ex.getCause();
        } catch (Exception ex) {
            return ex + " - " + ex.getCause();
        }
        
        return "" + steps;
    }
    
    private ArrayList<String> createPossibleGuessArray(String prefix, String str)
    {
        ArrayList<String> possibleGuess = new ArrayList<>();
        int n = str.length();
        if (n == 0) {
            possibleGuess.add(prefix);
        } else {
            for (int i = 0; i < n; i++) {
                possibleGuess.addAll(createPossibleGuessArray(prefix + str.charAt(i), str.substring(i + 1, n) + str.substring(0, i)));
            }
        }
        return possibleGuess;   
    }
}

Servlet (MGame), realizuje grę. W nim oba EJB wstrzyknięte są prawidłowo i bez problemów.

public class MGame extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String steps = "";
        PrintWriter out = response.getWriter();
        try {
            response.setContentType("text/html;charset=UTF-8");
            request.setCharacterEncoding("UTF-8");
            
            Context context = new InitialContext();
            //IGameMonitor gameMonitor = (IGameMonitor) context.lookup("java:global/ejb-project/IGameMonitor!pl.jrj.game.IGameMonitor");
            IGameMonitor gameMonitor = (IGameMonitor) context.lookup(IGameMonitor.class.getName());
            //IMasterMind masterMind = (IMasterMind) context.lookup("java:global/ejb-project/IMasterMind!pl.jrj.game.IMasterMind");
            IMasterMind masterMind = (IMasterMind) context.lookup(IMasterMind.class.getName());
            
            Map<String, String> messages = new HashMap<>();
            request.setAttribute("messages", messages);
            
            String m = request.getParameter("m");
            //MasterMind masterMind = new MasterMind();
            
            if(gameMonitor.register(5, "98142")) {
                gameMonitor.initGame(m);
                steps = masterMind.playGame();
            }
            out.println(steps);
        } catch (NamingException ex) {
            out.println(ex);
        } catch (Exception ex) {
            out.println(ex);
        }
    }


    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }


    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

}

Jakieś pomysły co zrobić, żeby to zadziałało?

0

Ale czemu nie wstrzykniesz go przez adnotacje @EJB?

0

Próbowałem i rownież uważał że nie ma czegoś takiego. Ale mogłem to źle zrobić. Trzeba dodawac jakieś dodatkowe adnotacje we wstrzykiwanym EJB żeby to dzialało? Czy sama pojedyncza adnotacja bez dodatkowego kodu powinna załatwic sprswe?

0

Jeśli oba śmigają na tym samym kontenerze, to nie powinno być problemu. W zasadzie mógłyś równie dobrze użyć @Inject.

0

Trzeba tylko pamiętać, aby wstrzykiwać na zmienną, która ma typ interfejsu (a nie konkretnej klasy ejb) oraz, aby interfejs ejb miał anotację @JAVAX.ejb.Local

0

Można też wyszukać poprzez JNDI lookup, np.:
ExampleLocal example = (ExampleLocal)InitialContext.lookup("java:module/ExampleLocal");

a tutaj niedostępny z poziomu google tutorial:
http://docs.oracle.com/javaee/6/tutorial/doc/gipjf.html

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