-1

単純な JSON リストを取得し、この JSON 配列を Eclipselink オブジェクトに変換して、postgres に配置しようとしています。私は EntityManager から nullpointers を取得し続けていますが、追跡を失いました。

テスト Web サービスからコントローラーを呼び出しています。

@WebServlet(name = "Test", urlPatterns = {"/Test"})
public class Test extends HttpServlet {


    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            // HERE I CALL CUSTOM METHODS
            AppController appConn = new AppController();
            appConn.updateAppList();
        } finally {            
            out.close();
        }
    }

コントローラーで、これらの変換されたオブジェクトを永続化しようとしています:

public class AppController {
    @PersistenceUnit(unitName="UserPU")
    EntityManagerFactory emf;
    EntityManager em = emf.createEntityManager();


    public AppController() {

    }

    public void updateAppList() {
        try {
            URLController urlConn = new URLController(Config.allAppsURL);
            JsonElement jelement = new JsonParser().parse(urlConn.toString());
            JsonObject  jobject = jelement.getAsJsonObject();
            jobject = jobject.getAsJsonObject("applist");
            JsonArray jarray = jobject.getAsJsonArray("apps");

            ArrayList<SteamApp> apps = new ArrayList<App>(){};
            for(int i = 0; i < jarray.size(); i++) {
                JsonObject jsteamObject = jarray.get(i).getAsJsonObject();
                App app = new SteamApp(jsteamObject.get("appid").getAsLong(), jsteamObject.get("name").toString());
                apps.add(app);
                //System.out.println("App[" + app.getAppid() + ", " + app.getName() + "] \n\r");
            }

            em.persist(apps);
            em.flush();

        } catch (Exception ex) {
            Logger.getLogger(AppController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

このメソッドを Web サービスから呼び出して、テストするだけです。バックグラウンドで、それを引き込むために別のスレッドを使用することを計画しています。

しかし、私は何を間違っていますか?この持続性のセットアップは非常にわかりにくい?!?

4

1 に答える 1

2

主な問題は、AppControllerが管理対象オブジェクトではないため、依存性注入が実行されないことです。をマネージド Bean としてサーブレットに注入するか、ユーティリティ クラスを使用してAppController手動で初期化する必要があります。が完全にステートレスである場合は、アノテーションを使用して CDI マネージド Bean として注入できます。EntityManagerFactoryjavax.persistence.PersistenceAppController@Inject

AppController を注入する場合の別の問題はEntityManagerFactory、オブジェクトが構築された後にのみ注入されAppControllerますが、オブジェクトの構築中にフィールドが初期化されることです。新しい AppController オブジェクトが作成されると、emfフィールドは null に初期化されるため、フィールドを初期化しようとするとemnull ポインター例外が発生します。

EntityManagers もスレッドセーフではないため、CDI を介して注入する場合は、メソッドEntityManager内のファクトリからを作成する必要があります。updateAppList()これには、トランザクションの管理とエンティティ マネージャーの終了が自分の責任になるという欠点があります。

AppController別の方法として、 を EJB ステートレス セッション Beanに変換してから、これをサーブレットに注入します。この場合、EntityManagerFactory を注入する必要はありませんが、アノテーションEntityManagerを使用して直接注入できます。@PersistenceContext

于 2012-12-30T22:16:49.020 に答える