Java EE6æ¨æºã®ç¯å²ã§ãã«ã¹ã¿ãã¯ã®Webã¢ããªã±ã¼ã·ã§ã³ãç°¡åã«ä½æã§ãããã¨ã確ããã¦ã¿ã¾ããã
Java EE6ã§ããã«éçºã¯å®¹æã«ãªã£ãï¼
以åJavaEE標準の進化から最近の業務アプリケーション開発手法の変遷について考える - 達人プログラマーを目指してã«ã¦Java EEæ¨æºã®éçºã¢ãã«ã®é²åã«ã¤ãã¦èª¬æãã¾ããã10å¹´åã®ç¸å½é¢åã ã£ãJ2EEã®éçºã¢ãã«ã¨æ¯ã¹ã¦ãææ°ã®Java EE6ã§ã¯ãæ§ã ãªOSSã®è¯ãç¹å¾´ãåãå ¥ãã¦ãç°¡åã«ããã°ã©ãã³ã°ã§ããããã«å¤§å¹ ã«æ¹è¯ããã¦ãã¾ããã¾ããGlassfish 3.1ãJBoss AS7ãªã©ã¯èµ·åæéãé常ã«ç縮ããã¦ãã*1ããã»ã©é ãPCã§ãªããã°ãããæ°ç§ã§åèµ·åãããã¨ãã§ãã¾ããããã«ãJava EEサーバーが重くてテスト不能というイメージはもう過去の話かもしれない - 達人プログラマーを目指してã§ç´¹ä»ããããã«ãJava EE6ã§ã¯å¾æ¥å°é£ã§ãã£ãåä½è©¦é¨ã®èªååã容æã«ãªã£ã¦ãã¾ãã
åã ã®æè¡ã¯åªãã¦ããã®ã ããã©é©åãªãã«ã¹ã¿ãã¯ã®ãµã³ãã«ããªã
ãã¾ãããJava EEã®æ©è½ããã«ã«æ´»ç¨ãã¦ã¨ã³ã¿ã¼ãã©ã¤ãºJavaã¢ããªã±ã¼ã·ã§ã³ã楽ã«éçºãã¾ãããã
ã¨ãèªä¿¡ãæã£ã¦è¨ãããã¨ããã ã£ãã®ã§ããããããJava EE6ã®æ©è½ãçµã¿åããã¦ã¢ããªã±ã¼ã·ã§ã³ãéçºãããã¨ãã¦ããå®ã¯ãªããªãè¯ããµã³ãã«ã¨ããããææ¬ãè¦ã¤ãããªãã¨ããåé¡ãããã¾ããJava EE6ã®ããã¥ã¡ã³ãã¯å°ãªãã¨ãè±èªã§ã¯æ§ã
ãªãã¥ã¼ããªã¢ã«ãWebä¸ãæ¸ç±ã§è¦ã¤ããã®ã§ãããJSFãJPAãªã©ç¹å®ã®æè¡è¦ç´ ãã¿ã¼ã²ããã«ãã説æãã»ã¨ãã©ã§ãç»é¢ãããã¼ã¿ã¢ã¯ã»ã¹ã¾ã§ãçµã¿åãããå®æ¡ä»¶ã§ä½¿ããããªãããææ¬ããªããªãç¾æç¹ã§ã¯è¦ã¤ãããªãããã§ãã
ããã§ãNetBeansã§èªåçæå¯è½ãªJSF2ã®ãµã³ãã«ã¢ããªã±ã¼ã·ã§ã³ã§ãããJsfScrumToysããªãã¡ã¯ã¿ãªã³ã°ããEJBãCDIãJPAã¨çµã¿åãããããã«ä¿®æ£ãã¦ã¿ã¾ãããæåã¯ç°¡åã«ã§ããã¨äºæ³ãã¦ããã®ã§ãããåç´ãªCRUDå¦çã®ã¢ããªã±ã¼ã·ã§ã³ãä½æããã ãã§ããæ³å®å¤ã®è©¦è¡é¯èª¤ãããããã¨å¿
è¦ã§ãæºè¶³ãªè¨è¨ã«å°éããã¾ã§ã«çµæ§æéãããã£ã¦ãã¾ãã¾ãããããã§ããæçµçã«ã¯æ¨æºæè¡ã®ã¿ã§å®éã«ããªãç°¡åã«æ¸ãããã¨ããããã¾ããã®ã§ããã§ç´¹ä»ããã¦ããã ãã¾ãã
ãªãã¡ã¯ã¿ãªã³ã°çµæã¯ä»¥ä¸ã«ã¢ãããã¦ããã¾ããä¾å¤å¦çãªã©ãå®æ¡ä»¶ã¸ã®é©ç¨ã«å¯¾ãã¦ã¯ã¾ã ã¾ã èæ
®ã足ãã¦ããªãé¨åãããã¾ãããJava EE6éçºã®ãã¼ã¹ã¨ãã¦ä½¿ã£ã¦ããã ããã¨æãã¾ãã
GitHub - ryoasai/jsf-scrumtoys-refactored: A sample web application using Java EE6 stack.
æ¬ã¨ã³ããªã«é¢é£ãã¦ä»¥ä¸ã®ã¾ã¨ãããåç
§ãã ããã
JavaEE6を使ったアプリケーション開発について - Togetter
ãªãªã¸ãã«ã®ScrumToysã®åé¡ç¹
ãªãªã¸ãã«ã®ScrumToysã¢ããªã±ã¼ã·ã§ã³ã¯ãNetBeansãç¨ãã¦èªåçã«çæãããã¨ãã§ãã¾ãã
ãã®ã¢ããªã±ã¼ã·ã§ã³ã¯ä»¥ä¸ã®ãããªãã¡ã¤ã³ã¢ãã«ã®ã¨ã³ãã£ãã£ã«å¯¾ãã¦ãåã¨ã³ãã£ãã£ã®CRUDå¦çãå®ç¾ããç°¡åãªã¢ããªã±ã¼ã·ã§ã³ã¨ãªã£ã¦ãã¾ãã
ç¹ã«ç¹æ®ãªã¨ããã¯ãªããåã«ãäºãã«å
¥ãåã®é¢ä¿ã«ããã¨ã³ãã£ãã£ã管çããã¢ããªã±ã¼ã·ã§ã³ã«ãªã£ã¦ãã¾ããç¬ç«ããåãã¼ãã«ã®CRUDå¦çã«æ¯ã¹ã¦é¢é£ãé©åã«å¦çããªãã¦ã¯ãªããªãã¨ãããå¤å°é£ããã¨ããã§ãã
ãªãªã¸ãã«ã®å®è£
ã¯åºæ¬çã«JSF2ã®æ°æ©è½ã®ãã¢ã¨ããä½ç½®ã¥ãã®ãããç¹ã«ãã¼ã¿ã¢ã¯ã»ã¹å±¤ãHTTPã»ãã·ã§ã³ã®ç®¡çãªã©ã¯ç°¡æåã§ãããã¤ã³ããããããæ®ã£ã¦ãã¾ãã
ãã¼ã¿ã¢ã¯ã»ã¹æã®ãã©ã³ã¶ã¯ã·ã§ã³ç®¡çãé¢å
ã¾ãããã©ã³ã¶ã¯ã·ã§ã³ã®ç®¡çã¯EJBã使ããã以ä¸ã®ããã«ç¬èªã«ã³ã¼ã«ããã¯ãã¿ã¼ã³ã使ã£ã¦å®è£ ããã¦ãã¾ãã
@PersistenceUnit private EntityManagerFactory emf; @Resource private UserTransaction userTransaction; protected final <T> T doInTransaction(PersistenceAction<T> action) throws ManagerException { EntityManager em = emf.createEntityManager(); try { userTransaction.begin(); T result = action.execute(em); userTransaction.commit(); return result; } catch (Exception e) { try { userTransaction.rollback(); } catch (Exception ex) { Logger.getLogger(AbstractManager.class.getName()).log(Level.SEVERE, null, ex); } throw new ManagerException(e); } finally { em.close(); } }
ããã¦ãåå¥ã®Managerã¯ã©ã¹ã§ä»¥ä¸ã®ããã«ãã¼ã¿ã¢ã¯ã»ã¹ãå®è¡ãã¾ãã
public String remove() { final Project project = projects.getRowData(); if (project != null) { try { doInTransaction(new PersistenceActionWithoutResult() { public void execute(EntityManager em) { if (em.contains(project)) { em.remove(project); } else { em.remove(em.merge(project)); } } }); getProjectList().remove(project); } catch (Exception e) { getLogger(getClass()).log(Level.SEVERE, "Error on try to remove Project: " + getCurrentProject(), e); addMessage("Error on try to remove Project", FacesMessage.SEVERITY_ERROR); return null; } } init(); // Using implicity navigation, this request come from /projects/show.xhtml and directs to /project/show.xhtml // could be null instead return "show"; }
ã³ã¼ã«ããã¯ãã¿ã¼ã³ã使ã£ã¦ããç¨åº¦å¦çãå ±éåãã¦ãããã®ã®ãããã§ãç¸å½ã®é³åã³ã¼ã(boilerplate code)ã®è¨è¿°ãå¿ è¦ã«ãªã£ã¦ãã¾ããJava EE5ã¾ã§ã¯EJBãå©ç¨ããã®ããããªãã«é¢åã ã£ãï¼earãã¡ã¤ã«ã使ãå¿ è¦ããããªã©ï¼ã®ã§ãããEJBã使ããªãéãæ¨æºã®ç¯å²å ã§ã¯ã³ã³ãã管çã®æ°¸ç¶ã³ã³ããã¹ããé©åã«å©ç¨ã§ããªããã*2ããã®ãããªåé·ãªã³ã¼ãã¯ãããå¾ãªãã¨ãããããã¾ããã
ã»ãã·ã§ã³ã®è¥å¤§å
ãªãªã¸ãã«ã®ScrumToysã§ã¯ã»ã¨ãã©ã®BeanãSessionã¹ã³ã¼ãã«ä¿æãã¦ãã¾ãã
@ManagedBean(name = "sprintManager") @SessionScoped public class SprintManager extends AbstractManager implements Serializable { private static final long serialVersionUID = 1L; private Sprint currentSprint; private DataModel<Sprint> sprints; private List<Sprint> sprintList; @ManagedProperty("#{projectManager}") private ProjectManager projectManager; private Project currentProject; ... }
DataTableãªã©JSFã®å¤ãã®ã³ã³ãã¼ãã³ãã¯ç»é¢è¡¨ç¤ºä¸ãã¼ã¿ãã¡ã¢ãªä¸ã«ä¿æããã¦ãããã¨ãåæã¨ãã¦ãããã¨ãããããããä»æ¹ããªãã¨ãããããã¾ãããã ããä¸è¨ã®ä¾ãè¦ã¦ããããããã«æ¤ç´¢çµæããã¹ã¦ã¡ã¢ãªä¸ã«ä¿æãã¦ããã°ã¢ã¦ãã¾ã§ã¯ãªã¢ãããªãç¶æ
ã«ãªã£ã¦ãã¾ã£ã¦ãã¾ããæ¤ç´¢ãããã¼ã¿éãåæãã°ã¤ã³ã¦ã¼ã¶ã¼æ°ãå¢ããã°ããã¯æ§è½ä¸ã®åé¡ã¨ãªãå¯è½æ§ãé«ãã§ãããç¹ã«ã¯ã©ã¹ã¿ç°å¢ã§ã¯è¥å¤§ããã»ãã·ã§ã³ã®ã¬ããªã±ã¼ã·ã§ã³ã¯æ§è½ä¸å¤§ããªãªã¼ãã¼ãããã«ãªã£ã¦ãã¾ãã¾ãã
ãããããæå¤ã«ç¥ããã¦ããªãäºå®ã§ãããä¸è¨ã®ã³ã¼ãã¯ã¹ã¬ããã»ã¼ãã§ã¯ããã¾ãããSessionScopeãApplicationScopeã®ç®¡çBeanã¯ä¸¦è¡ã¢ã¯ã»ã¹ã«å¯¾ãã¦ããã©ã«ãã§ã¯ä¿è·ãããªãããã§ãããããããµã³ãã«ã¢ããªã±ã¼ã·ã§ã³ã§ã¯åé¡ã«ãªããªãã¦ããå®éã®æ¡ä»¶ã«é©ç¨ããéã«ã¯åé¡ã§ãã
æåã®ç¶æ åæ
ScrumToyã®ã¢ããªã±ã¼ã·ã§ã³ã®ã»ã¨ãã©ã¯CRUDå¦çãªã®ã§æ¬æ¥æ¥åãã¸ãã¯ã¯ã»ã¨ãã©ãªãã®ã§ãããã¡ã¢ãªä¸ã«ä¿æãã¦ããã¨ã³ãã£ãã£ã®ç¶æ ãæåã§åæããã³ã¼ããããªãã®åéè¨è¿°ããã¦ãã¾ãã
public String save() { if (currentSprint != null) { try { Sprint merged = doInTransaction(new PersistenceAction<Sprint>() { public Sprint execute(EntityManager em) { if (currentSprint.isNew()) { em.persist(currentSprint); } else if (!em.contains(currentSprint)) { return em.merge(currentSprint); } return currentSprint; } }); if (!currentSprint.equals(merged)) { setCurrentSprint(merged); int idx = sprintList.indexOf(currentSprint); if (idx != -1) { sprintList.set(idx, merged); } } getProjectManager().getCurrentProject().addSprint(merged); if (!sprintList.contains(merged)) { sprintList.add(merged); } } catch (Exception e) { getLogger(getClass()).log(Level.SEVERE, "Error on try to save Sprint: " + currentSprint, e); addMessage("Error on try to save Sprint", FacesMessage.SEVERITY_ERROR); return null; } } return "show"; }
ã¡ã¢ãªä¸ã«ã¨ã³ãã£ãã£ã®ç¶æ ãä¿æãã¦ãããããã©ããã§æ´æ°å¦çãè¡ã£ãå ´åã«æ£ããç¶æ ãåæãã¦ãããªãã¨ä¸æ´åã«ãªã£ã¦ãã¾ãããã§ããããã¯ä¸è¬ã«ãã®ãããªã¹ãã¼ããã«ã®ã¢ããªã±ã¼ã·ã§ã³ãè¨è¨ããéã®ãã£ã¨ãé£ãããã¤ã³ãã«ãªãã®ã§ãããæ¬æ¥åãIDã®ã¨ã³ãã£ãã£ã§ãã£ã¦ãè¤æ°ã®ã¤ã³ã¹ã¿ã³ã¹ãåå¨ããå ´åããäºãã®ç¶æ ãåæãã¦ããå¿ è¦ãããã¾ããæåã§ãã®ãããªåæãæ¯åè¡ãã®ã¯é¢åã§ãããã°ã®åå ã«ãªãã¾ãã
EJBã®å°å ¥ã«ãããã©ã³ã¶ã¯ã·ã§ã³ç®¡çã®ç°¡æå
æ¹è¯çã§ã¯ãEJB3.1ãçµã¿åããããã¨ã§ãã¾ããæåã®åé¡ã§ãããã©ã³ã¶ã¯ã·ã§ã³ç®¡çãé¢åãªç¹ã解æ¶ãã¦ãã¾ããEJB3.1ã§ã¯ã
- earãã¡ã¤ã«ãä½æããå¿ è¦ããªãwarãã¡ã¤ã«ä¸ã«æ ¼ç´ã§ããã
- ã¤ã³ã¿ã¼ãã§ã¼ã¹ã¯ãªãã·ã§ã³
ã¨ãããã¨ãããã以åã®EJB3.0ã®é ã¨æ¯è¼ãã¦å°å
¥ã®æ·å±
ã¯å®éã«ããªãä¸ãã£ã¦ãã¾ãã
ã¾ããé常ããè¡ããã¦ããGenericDaoãã¿ã¼ã³ã®ããã«ä»¥ä¸ã®ãããªè¦ªã¯ã©ã¹ãå®ç¾©ãã¦ããã¾ãã
public abstract class JpaRepository<K extends Serializable, E extends PersistentEntity<K>> implements Repository<K, E> { private Class<E> entityClass; @PersistenceContext protected EntityManager em; public JpaRepository(Class<E> entityClass) { this.entityClass = entityClass; } @Override public E findById(K id) { return em.find(entityClass, id); } @Override @SuppressWarnings("unchecked") public List<E> findByNamedQuery(String queryName) { return (List<E>) em.createNamedQuery(queryName).getResultList(); } @Override public E persist(E entity) { if (entity.isNew()) { em.persist(entity); return entity; } else { return entity; } } @Override public void remove(K id) { E managed = findById(id); em.remove(managed); } @Override public void remove(E entity) { remove(entity.getId()); } }
ããã¦ããããç¶æ¿ããåã¨ã³ãã£ãã£ç¨ã®ã¬ãã¸ããªã¯ã©ã¹ãã¹ãã¼ãã¬ã¹EJBã¨ãã¦ä»¥ä¸ã®ããã«ä½æããããã«ãã¾ããã
@Stateless public class ProjectRepository extends JpaRepository<Long, Project> { public ProjectRepository() { super(Project.class); } public long countOtherProjectsWithName(Project project, String newName) { Query query = em.createNamedQuery(project.isNew() ? "project.new.countByName" : "project.countByName"); query.setParameter("name", newName); if (!project.isNew()) { query.setParameter("currentProject", project); } return (Long) query.getSingleResult(); } }
é常ã®GenericDaoãã¿ã¼ã³ã¨åæ§ã«ãæ£ããã¤ã³ã¿ã¼ãã§ã¼ã¹ãå®ç¾©ãã¦å®è£ ããã¦ãè¯ãã®ã§ãããããã§ã¯EJB3.1ã®ãã¼ã¤ã³ã¿ã¼ãã§ã¼ã¹ãã¥ã¼ã®æ©è½ã使ããã¤ã³ã¿ã¼ãã§ã¼ã¹å®ç¾©ãçç¥ãã¦ãã¾ãã
JSFã®ç®¡çBeanãCDIã®ç®¡çBeanã«ä¿®æ£
ãªãªã¸ãã«ã§ã¯JSFã®ç®¡çBeanã¨ãã¦å®ç¾©ããã¦ããã®ã§ããããããCDIã®ç®¡çBeanã¨ãã¦å®ç¾©ããªããã¾ãããä¿®æ£ç¹ã¨ãã¦ã¯ã
import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; ... @ManagedBean(name = "skinManager") @SessionScoped public class SkinManager extends AbstractManager implements Serializable {
ã®ãããªå®£è¨ãã以ä¸ã®ããã«ä¿®æ£ãã¾ãã
import javax.enterprise.context.SessionScoped; import javax.inject.Named; ... @Named @SessionScoped public class SkinManager extends AbstractManager implements Serializable {
ããã§ãåç´åãåããªã®ã§ééããããã®ã§ããã@javax.faces.bean.SessionScopedã@javax.enterprise.context.SessionScopedã«ä¿®æ£ãã¦ãã¾ããï¼大混乱に陥っているJavaEE 6のアノテーションに関する使い分けについて - 達人プログラマーを目指してï¼
CDIãå©ç¨ãããã¨ã§ãJSFã®ç®¡çBeanã使ãå ´åã¨æ¯ã¹ã¦ä»¥ä¸ã®ã¡ãªãããããã¾ãã
- ä¼è©±ã¹ã³ã¼ãã使ããï¼ç¹å®ã®ç»é¢é·ç§»ã®éã®ã¿ã¡ã¢ãªã«ä¿æããï¼
- EJBãå«ãã¦ä»ã®ä»»æã®Beanã@Injectã§ã¤ã³ã¸ã§ã¯ã·ã§ã³ã§ããããã«ãªãã
- ã¤ã³ã¸ã§ã¯ã·ã§ã³å¯¾è±¡ãæååãã¼ã¹ã§ãªãã¦åãã¼ã¹ãªã®ã§ééãã«ããã
- EJBãã®ãã®ã管çBeanã¨ãã¦JSFã®ç»é¢ããå©ç¨ã§ããããã«ãªãã
@SessionScopedã@ConversationScopedã«ä¿®æ£
@SessionScopedã®Beanã¯ãã°ã¤ã³ä¸ãã£ã¨ç¶æ ãä¿æããã¾ããã@ConversationScopedã®Beanã¯ããã°ã©ã ä¸ã§ä¼è©±ã®éå§ã¨çµäºãæ示ãããã¨ã§ã¡ã¢ãªã®ç¶æ ãå¹ççã«ç®¡çãããã¨ãã§ãã¾ããå®éã以ä¸ã®ãããªãã¼ã¹ã¯ã©ã¹ãä½æããConversationã@Injectã«ããã¤ã³ã¸ã§ã¯ã·ã§ã³ãããã¨ã§ãä¼è©±ã®éå§ã¨çµäºãã³ã³ããã¼ã«ããããã«ãã¦ã¿ã¾ããã
public abstract class BaseCrudAction<K extends Serializable, E extends PersistentEntity<K>> extends AbstractAction implements Serializable { ... @Inject protected Conversation conversation; // ä¼è©±ãbiginãã¦ããç¶æ ä¸ã®ã¿è¤æ°ãªã¯ã¨ã¹ãã«ã¾ããã£ã¦ç¶æ ãä¿æãããã public void beginConversation() { if (conversation.isTransient()) { conversationNested = false; conversation.begin(); } else { conversationNested = true; } } // ä¼è©±ãbiginãã¦ããªãããããã¯endãå¼ã³åºããå¾ã¯åãªã¯ã¨ã¹ãçµäºå¾ã«è§£æ¾ãããã public void endConversation() { if (!isConversationNested() && !conversation.isTransient()) { conversation.end(); } this.currentEntity = null; } ...
ç¬èªã®@ViewScopedãä½æãã¦æ¤ç´¢çµæãä¿æããã
ãã®æç¹ã§åé¡ã¨ãªã£ããã¨ãããã¾ããä¼è©±ã¹ã³ã¼ãã«ããã¡ã¢ãªã®è§£æ¾ã管çã§ããããã«ãªã£ãã®ã§ãããä¼è©±ããã¤beginããendããã°ããã®ãã¨ãããã¨ãé©åã«è¨è¨ããå¿
è¦ãããã¨ããç¹ã§ãããã¡ãããæåããä¼è©±ãbeginãããã¨ã§ããã¨ãã¨ã®Sessionã¹ã³ã¼ãã®æã¨åæ§ã®åä½ãããããã¨ãã§ããã®ã§ãããããã§ã¯ãã»ãã·ã§ã³ã®è¥å¤§åã¨ãããã¨ãã¨ã®åé¡ã解決ããã¾ããã
é常èããããããã¹ãè¨è¨ã¨ãã¦ã¯ã
- ä¸è¦§è¡¨ç¤ºã¯ä¼è©±ã®å¤ã§è¡ãã
- ç¹å®ã®è¡ãç»é¢ã§é¸æãã¦å ¥åãã©ã¼ã ç»é¢ã表示ãããã¿ã¤ãã³ã°ã§ä¼è©±ãéå§ããã
- æ´æ°ãä½æããã£ã³ã»ã«ãªã©ã®å¦çå®è¡æã«ä¼è©±ãçµäºããã
- è¡åé¤ã¯ä¼è©±ãéå§ãããã«å®è¡ããã
ã¨ããæ¹æ³ã§ãã
ãããããã®æ¹æ³ããã®ã¾ã¾å©ç¨ããã®ã§ã¯ãã¾ããããªããã¨ããããã¾ããããªããªããJSFã®DataTableã¯è¡¨ç¤ºæã¨ãã¹ãããã¯æã§ãã¼ã¿ãä¿æããã¦ãããã¨ãåæã®ããã§ããä¸è¦§è¡¨ç¤ºãä¼è©±ã®å¤ã§è¡ã£ãå ´åããã¹ãããã¯æã«ãã¼ã¿ãæ¶ãã¦ãã¾ããããã¼ãã«ä¸ã®è¡é¸æãæ£ããåä½ãã¾ããã
ä¸è¦§ãã¼ã¿ãé·æéä¿æããããªãã®ã«ãå°ãªãã¨ãå¤ãã®JSFã®ã³ã³ãã¼ãã³ãã¯åä¸ç»é¢ã¸ã®ãã¹ãããã¯æã«ãã¼ã¿ãæ®ã£ã¦ãããã¨ãæå¾
ãã¦ãã¾ãã
JSFã®å ´å@javax.faces.bean.ViewScopedã§æå®ããããã¥ã¼ã¹ã³ã¼ãã¨ãããã®ãããã¾ãããã®ã¹ã³ã¼ãã使ãã¨ã»ãã·ã§ã³ãä¼è©±ã¹ã³ã¼ãã«ãã¼ã¿ãä¿åããªãã¦ããä¸ã¤ã®ãã¥ã¼ã表示ãã¦ããæä¸ã®ã¿ãã¼ã¿ãä¿æããããã¨ãã§ã便å©ã§ããåé¡ãªã®ã¯ãJSFã¨CDIãçµã¿åãããä¸ã§ä¾¿å©ãªãã¥ã¼ã¹ã³ã¼ããCDIã®æ¨æºã§ã¯å®ç¾©ããã¦ããªããã¨ã§ããããã§ãããããããæ¹ãæ¢ãã¦ããã®ã§ããã以ä¸ã®ãµã¤ãã«æ¹æ³ãæ¸ããã¦ãã¾ããã
http://www.verborgh.be/articles/2010/01/06/porting-the-viewscoped-jsf-annotation-to-cdi/
ãã®æ¹æ³ã«å¾ãã¨ãæå¤ã«ç°¡åã«CDIã§ç¬èªã®ãã¥ã¼ã¹ã³ã¼ããå®ç¾©ãããã¨ãå¯è½ã§ããã¾ãã以ä¸ã®ããã«ViewScopedã®ã¢ããã¼ã·ã§ã³ãå®ç¾©ãã¾ãã
@Inherited @NormalScope @Retention(RUNTIME) @Target({METHOD, FIELD, TYPE}) public @interface ViewScoped { }
次ã«ã以ä¸ã®ããã«Contextã¨SystemEventListenerãå®è£ ããViewScopedContextãä½æããJSFã®ãã¥ã¼ã«é¢ããã¤ãã³ãããã³ããªã³ã°ãã¦ãã¼ã¿ãJSFã®UIããªã¼ä¸ã§æ£ãã管çãããã¸ãã¯ãå®è£ ãã¾ãã
public class ViewScopedContext implements Context, SystemEventListener { ... }
ããã¦ã以ä¸ã®ãããªCDIã®Extentionãä½æãã¦ä¸è¨ã®ã¯ã©ã¹ãç»é²ãã¾ãã
public class ViewScopedExtension implements Extension { public void addScope(@Observes final BeforeBeanDiscovery event) { event.addScope(ViewScoped.class, true, true); } public void registerContext(@Observes final AfterBeanDiscovery event) { event.addContext(new ViewScopedContext()); } }
æå¾ã«ã以ä¸ã®ExtentionãMETA-INF/servicesé
ä¸ã®javax.enterprise.inject.spi.Extensionã¨ããååã®ãã¡ã¤ã«ä¸ã§ç»é²ãã¾ãã
以ä¸ã®æ¡å¼µãè¡ããã¨ã§ãæ¤ç´¢çµæã®ãªã¹ãããã¥ã¼ã¹ã³ã¼ãã«ä¿æã§ããããã«ãªãã¾ããä¾ãã°ã以ä¸ã®ãããªCDIã®çæã¡ã½ãããè¨è¿°ãããã¨ã§ãæ¤ç´¢çµæã®ãªã¹ãããã¥ã¼ã¹ã³ã¼ãã«ä¿æã§ãã¾ãã
@Produces @Named @ViewScoped public List<Project> getProjects() { return projectRepository.findByNamedQuery("project.getAll"); }
ãããã£ã¦ãJSFã®ãã¼ãã«ã§ä»¥ä¸ã®ããã«ãã¦æ£ãã表示ãããã¨ãã§ãã¾ãã
<h:dataTable value="#{projects}" var="project" rendered="#{not empty projects}" title="#{i18n['project.show.table.title']}" summary="#{i18n['project.show.table.title']}" border="0" headerClass="datatableHeader" rowClasses="datatableRow,datatableRow2" columnClasses="dataTableFirstColumn" styleClass="datatable" id="dtProjects"> <h:column> <f:facet name="header">#{i18n['project.show.table.header.name']}</f:facet> #{project.name} </h:column> <h:column> <f:facet name="header">#{i18n['project.show.table.header.startDate']}</f:facet> <h:outputText value="#{project.startDate}"> <f:convertDateTime pattern="#{i18n['project.show.table.header.startDate.pattern']}" /> </h:outputText> </h:column> ....
ã¹ãã¼ããã«ã»ãã·ã§ã³Beanãå©ç¨ãã¦ã¨ã³ãã£ãã£ã®ä¸ææ§ãèªåçã«ä¿éããã
æå¾ã«ãç¶æ
ã®åæã®åé¡ã«ã¤ãã¦èãã¾ããJPAã§ã¯æ°¸ç¶ã³ã³ããã¹ããããããããæç¶ãã¦ããæéä¸ã¯èªåçã«ã¨ã³ãã£ãã£ã®ä¸ææ§ãä¿è¨¼ãã¦ãããããã«ãªã£ã¦ãã¾ããï¼Identity Mapãã¿ã¼ã³ãO/Rマッピングで緩和されるインピーダンスミスマッチには静的と動的の側面がある - 達人プログラマーを目指してï¼
ãããã£ã¦ãåºæ¬çãªçºæ³ã¨ãã¦ãCDIã®ä¼è©±ã¹ã³ã¼ããç¶ç¶ãã¦ããæä¸ãã£ã¨JPAã®æ°¸ç¶ã³ã³ããã¹ããæç¶ããããã¨ã§ãã¨ã³ãã£ãã£ã®ç¶æ
管çã¨ãã£ãã·ã¥ãJPAã«ä»»ãã¦ãã¾ããã¨ãã§ããã°ã¢ããªã±ã¼ã·ã§ã³å´ã®ç¶æ
管çã大å¹
ã«ç°¡åã«ãªãã¯ãã§ãã
è¤æ°ã®DBãã©ã³ã¶ã¯ã·ã§ã³ãã¾ããã£ã¦é·æéJPAã®æ°¸ç¶ã³ã³ããã¹ããæç¶ãããã«ã¯ã
- ã¹ãã¼ããã«ã»ãã·ã§ã³Beanã使ã
- ã¹ãã¼ããã«ã»ãã·ã§ã³Beanãä¼è©±ã¹ã³ã¼ãã«ä¿æãã
- @PersistenceContext(type= PersistenceContextType.EXTENDED)ã¨ããã¢ããã¼ã·ã§ã³ã使ã£ã¦EntityManagerãã¤ã³ã¸ã§ã¯ã·ã§ã³ãã
- EJBã®ããã©ã«ãã®ãã©ã³ã¶ã¯ã·ã§ã³å±æ§ãTransactionAttributeType.NOT_SUPPORTEDã«ãã¦åæã«DBã«æ´æ°ãè¡ãããªãããã«ããã
- æ¬å½ã«DBã«å¯¾ãã¦æ¸ãæããè¡ãããã¡ã½ããã«å¯¾ãã¦TransactionAttributeType.REQUIREDãä»ããã
ã¨ãã£ãè¦åã«å¾ãå¿
è¦ãããã¾ãã
å®éã«è©¦ãã¦ã¿ã¦åãã£ãã®ã§ããããã®æ¹å¼ã§æãåé¡ã¨ãªãã®ã¯EXTENDEDæå®ãããæ°¸ç¶ã³ã³ããã¹ãã®ä¼æ¬ã®å¶ç´ã§ããçæ³çã«ã¯åä¸ã®ä¼è©±ã¹ã³ã¼ãå
ã§ããã°ãè¤æ°ã®Beanããåä¸ã®æ°¸ç¶ã³ã³ããã¹ãã®ã¤ã³ã¹ã¿ã³ã¹ã«ã¢ã¯ã»ã¹ãããã®ã§ãããç¾ç¶ã®Java EEã®ä»æ§ã§ã¯åä¸ã®ã¹ãã¼ããã«Beanããã¹ãã¼ãã¬ã¹Beanã«å¯¾ãã¦ã®ã¿æ£ããä¼æ¬ãããããã§ããç¹ã«ãè¤æ°ã®ã¹ãã¼ããã«Beanã«åå²ããå ´åãåä¸ã®æ°¸ç¶ã³ã³ããã¹ããç°¡åã«å
±æããããã¨ãã§ãã¾ããã*3
ã¨ãããããä»åã¯ãã®ã¢ããªã±ã¼ã·ã§ã³ã®ä¼è©±ã§ç®¡çãããã¹ã¦ã®ç¶æ
ãScrumManagerImplã¨ããä¸ã¤ã®ã¹ãã¼ããã«Beanã«éç´ãããã¨ã§å¯¾å¿ãããã¨ã«ãã¾ããã
@Stateful @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) @ConversationScoped public class ScrumManagerImpl implements ScrumManager, Serializable { private static final long serialVersionUID = 1L; //========================================================================= // Fields. //========================================================================= private Project currentProject; private Sprint currentSprint; private Story currentStory; private Task currentTask; @Inject ProjectRepository projectRepository; @Inject SprintRepository sprintRepository; @Inject StoryRepository storyRepository; @Inject TaskRepository taskRepository; @Inject @SuppressWarnings("NonConstantLogger") transient Logger logger; @PersistenceContext(type= PersistenceContextType.EXTENDED) protected EntityManager em; //========================================================================= // Bean lifecycle callbacks //========================================================================= @PostConstruct public void construct() { logger.log(Level.INFO, "new intance of {0} in conversation", getClass().getName()); } @PreDestroy public void destroy() { logger.log(Level.INFO, "destroy intance of {0} in conversation", getClass().getName()); } //========================================================================= // Project management //========================================================================= @Produces @Current @Named @Override public Project getCurrentProject() { return currentProject; } @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public void setCurrentProject(Project currentProject) { this.currentProject = projectRepository.toManaged(currentProject); currentSprint = null; currentStory = null; currentTask = null; } @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public void saveCurrentProject() { assertThatEntityIsNotNull(currentProject); if (!currentProject.isNew()) return; projectRepository.persist(currentProject); } @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public void removeProject(Project project) { projectRepository.remove(projectRepository.findById(project.getId())); } //========================================================================= // Sprint management //========================================================================= @Produces @Current @Named @Override public Sprint getCurrentSprint() { return currentSprint; } @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public void setCurrentSprint(Sprint currentSprint) { this.currentSprint = sprintRepository.toManaged(currentSprint); currentStory = null; currentTask = null; } @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public void saveCurrentSprint() { assertThatEntityIsNotNull(currentProject); assertThatEntityIsNotNull(currentSprint); if (!currentSprint.isNew()) return; currentProject.addSprint(currentSprint); } @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public void removeSprint(Sprint sprint) { assertThatEntityIsNotNull(currentProject); currentProject.removeSprint(sprint); } //========================================================================= // Story management //========================================================================= @Produces @Current @Named @Override public Story getCurrentStory() { return currentStory; } @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public void setCurrentStory(Story currentStory) { this.currentStory = storyRepository.toManaged(currentStory); currentTask = null; } @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public void saveCurrentStory() { assertThatEntityIsNotNull(currentSprint); assertThatEntityIsNotNull(currentStory); if (!currentStory.isNew()) return; currentSprint.addStory(currentStory); } @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public void removeStory(Story story) { assertThatEntityIsNotNull(currentSprint); currentSprint.removeStory(story); } //========================================================================= // Task Management //========================================================================= @Produces @Current @Named @Override public Task getCurrentTask() { return currentTask; } @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public void saveCurrentTask() { assertThatEntityIsNotNull(currentStory); assertThatEntityIsNotNull(currentTask); if (!currentTask.isNew()) return; currentStory.addTask(currentTask); } @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public void removeTask(Task task) { assertThatEntityIsNotNull(currentStory); currentStory.removeTask(task); } @TransactionAttribute(TransactionAttributeType.REQUIRED) @Override public void setCurrentTask(Task currentTask) { this.currentTask = taskRepository.toManaged(currentTask); } }
ãªããSeam3ã§ã¯ãã®åé¡ã«å¯¾å¦ãããããEXTENDEDæå®ãããæ°¸ç¶ã³ã³ããã¹ããå©ç¨ãã代ããã«ãã¢ããªã±ã¼ã·ã§ã³ç®¡çã®æ°¸ç¶ã³ã³ããã¹ããä¼è©±ã¹ã³ã¼ãã«çæãã¦ãä»»æã®Beanã«ã¤ã³ã¸ã§ã¯ã·ã§ã³ãã¦å
±æããããã¿ãåå¨ãã¾ãã
http://seamframework.org/Seam3/PersistenceModule
ãã ããæ®å¿µãªããç¾æç¹ã§ã¯äºææ§ä¸ã®åé¡ããããGlassfishä¸ã§ã¯åä½ãã¾ããã§ããã
ã¾ã¨ã
ã©ã¤ãã©ãªã¼ã®å©ããåãããJava EE6ã®æ¨æºæ©è½ã®ã¿ãå©ç¨ãã¦ç°¡åã«Webã¢ããªã±ã¼ã·ã§ã³ãä½æã§ãããã¨ã確ããããããJsfScrumToysã¨ãããµã³ãã«ã¢ããªã±ã¼ã·ã§ã³ããªãã¡ã¯ã¿ãªã³ã°ããå®é¨ã試ã¿ã¾ããã
- EJBã®ãã©ã³ã¶ã¯ã·ã§ã³ç®¡çãå°å ¥ããã
- CDIã®ä¼è©±ã¹ã³ã¼ããå°å ¥ããã
- CDIã®ãã¥ã¼ã¹ã³ã¼ããæ¡å¼µãã¦æ¤ç´¢çµæãä¿æã§ããããã«ããã
- ã¹ãã¼ããã«Beanã使ã£ã¦ç¶æ 管çãç°¡æåããã
ä»å¾ã
- å ±éå¦çã®ãããªããã¬ã¼ã ã¯ã¼ã¯å
- åä½è©¦é¨èªåå
- ããªãã¼ã·ã§ã³å¦çã®å ±éå
- ä¾å¤å¦ç
ãªã©ã®èª²é¡ãæ®ã£ã¦ãã¾ãããããã¤ãã®æ³¨æç¹ãå
æããã°ãJava EE6æ¨æºã®ç¯å²å
ã§å®éã«ããªãç°¡åã«Webã¢ããªã±ã¼ã·ã§ã³ãéçºã§ãããã¨ããããã¾ããã
ãã ãããã®ãããªç°¡åãªã¢ããªã±ã¼ã·ã§ã³ã§ããå®éã«ããã¤ãã®è½ã¨ãç©´ãããããã§ãã®ã§ãå®éã®ã¢ããªã±ã¼ã·ã§ã³ãéçºããéã«ã¯ããã°ã©ãã³ã°ã®æ¹å¼ãååã«ç 究ãã¦ã©ã®æè¡ãã©ã®ããã«çµã¿åãããã®ããèãããã¨ã大åã§ããã¨æãã¾ãããä»åã¯ãªãã¹ãåºç¯å²ã®æè¡ã®çµã¿åããã確èªãã¦ã¿ãã®ã§ãããå ´åã«ãã£ã¦ã¯JPAã ã使ããJSFã ã使ãã¨ãã£ããã¨ãé©åãªå ´åãããããããã¾ãããã¾ããä»åã¯ãªãªã¸ãã«ã®è¨è¨ãè¸è¥²ãã¦ã¹ãã¼ããã«ãªè¨è¨ã«ãã¾ããããå¾å¤±ãè¦æ¥µãã¦æ¡ç¨ãããã©ããæ¤è¨ããå¿
è¦ãããã¾ãã
*1:OSGiã¨ãã£ãã¢ã¸ã¥ã¼ã«åã®ãã¯ããã¸ã¼ãæ¡ç¨ãé«éåã«å¤§ããå¯ä¸ãã¦ãããããã
*2:ãµã¼ãã¬ãããªã©ã«@PersistenceContextã§ç´æ¥æ°¸ç¶ã³ã³ããã¹ããã¤ã³ã¸ã§ã¯ã·ã§ã³ããã®ã¯ã¹ã¬ããã»ã¼ãã§ã¯ãªãã
*3:JPAã®ä»æ§ã§ã¯ããã¹ãã¼ããã«Beanãèªåã§å¥ã®ã¹ãã¼ããã«BeanãJNDIã@EJBã«ããã¤ã³ã¸ã§ã¯ã·ã§ã³ã§æ示çã«çæããå ´åã«éããã¹ãã¼ããã«Beanéã§æ°¸ç¶ã³ã³ããã¹ããå ±æã§ããããã§ãããCDIã®ããã«ã³ã³ãããåBeanãçæããæ¹å¼ã§ã¯ãã¾ãå ±æã§ãã¾ããã