留言板

Portlet + annotációk

thumbnail
Tamás Sallai,修改在14 年前。

Portlet + annotációk

Junior Member 帖子: 44 加入日期: 09-9-17 最近的帖子
Sziasztok!

Próbálok egy egyszerű tesztportletet fejleszteni, nagyjából kész is, de elég sok mellékvágányt kellett tennem közben. Az a problémám, hogy a portlet class-ában metódusra vagy tagváltozóra tett annotációkat mintha figyelmen kívül hagyná.
JPA-val oldottam meg az adatbáziselérést, és pl nem tudok EntityManager-t injektálni, csak JNDI-vel lehet előkeresni. A tranzakciókezelést sem tudom deklaratívan megadni, hanem hasonlóan JNDI-vel kell egy UserTransaction-t szerezni, és manuálisan begin és committálni. Ezen kívül az EJB injektálást sem sikerült megoldanom, ott is sikerül egy referenciát szerezni, de (gondolom a classloader különbözőségéből) nem tudom castolni megfelelő típusra(tehát a referencia megvan, és getClass().invoke()-val tudom is hívni, de elég körülményes).

A portlet java kódjából az érdekesebb részek:
@PersistenceContext(name = "persistence/default", unitName = "default")
public class EmotionMeterPortlet extends GenericPortlet {

	@PersistenceContext(unitName="default")
	EntityManager m;
	
	public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
		System.err.println(m);
		response.setContentType("text/html");
		try {
			EntityManager manager = (EntityManager) new InitialContext().lookup("java:comp/env/persistence/default");
			List<emotion> ems = manager.createQuery(manager.getCriteriaBuilder().createQuery(Emotion.class)).getResultList();
			int pos = 5;
			if (ems.size() != 0) {
				pos = ems.get(0).getPosition();
			}
			response.getWriter().write("<span><form method="\&quot;POST\&quot;" action="\&quot;&quot;" + response.createActionURL() "\"><input type="\&quot;hidden\&quot;" name="\&quot;vote\&quot;" value="\&quot;minus\&quot;"><input type="\&quot;submit\&quot;" value="\&quot;-\&quot;"></form>TEST:" + pos + "<form method="\&quot;POST\&quot;" action="\&quot;&quot;" + response.createActionURL() "\"><input type="\&quot;hidden\&quot;" name="\&quot;vote\&quot;" value="\&quot;plus\&quot;"><input type="\&quot;submit\&quot;" value="\&quot;+\&quot;"></form></span>");
		} catch (Exception e) {
			e.printStackTrace();
		}

	}</emotion>

	public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException {
		boolean up = true;
		String param = request.getParameter("vote");
		if (param == null) {
			return;
		}
		if (param.compareTo("minus") == 0) {
			up = false;
		}
		try {
			EntityManager manager = (EntityManager) new InitialContext().lookup("java:comp/env/persistence/default");

			UserTransaction tr = (UserTransaction) new InitialContext().lookup("UserTransaction");
			tr.begin();
			int lastPos = 5;
			for (Emotion e : manager.createQuery(manager.getCriteriaBuilder().createQuery(Emotion.class)).getResultList()) {
				lastPos = e.getPosition();
				manager.remove(e);
			}
			Emotion e = new Emotion();
			e.setPosition(Math.min(Math.max(lastPos + (up ? 1 : -1), 1), 10));
			manager.persist(e);
			tr.commit();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


A portlet megtekintésénél az 'm' minden esetben null, de az adatbáziskezelés amúgy ilyen módon működik.

Ja, az alkalmazásszerver Glassfish v3, és war-ból van fent a Liferay(Mindkettőt néhány napja töltöttem, szal elég frissek)

Van esetleg valakinek valami ötlete, hogyan lehetne a CDI-t és a CMP-t rendesen kihasználni ilyen környezetben?
thumbnail
Tamás Sallai,修改在14 年前。

RE: Portlet + annotációk

Junior Member 帖子: 44 加入日期: 09-9-17 最近的帖子
Nohát, >1 napig próbálkoztam vele, mielőtt írtam ide, aztán rá néhány órával rá is jöttem a megoldásra. Úgy tűnik, hogy a portletek eléggé el vannak maradva az újításokból, azonban a servletek nem. Milyen szerencse, hogy a portletbe be lehet ágyazni őket. Ennek megfelelően írtam egy redirector portletet, ami megadott szervletnek átirányítja a kérést, egy servletet, amelyik feldolgozza, és ebbe lehet EJB-t is injektálni egyszerűen, abban pedig már lehet használni a CMP-t. Így portál környezetben fel lehet használni az alkalmazást, és az összes java EE 6-os meg majd későbbi jóság benne lesz.
Az osztályok, amiket írtam:

/** Servlet initparameter: target-servlet */
public class BaseRedirectorPortlet extends GenericPortlet {

	public static final String	parameterName	= "target-servlet";

	public static final String	modeParameter	= "BaseRedirector.mode";

	public static enum modes {
		VIEW, EDIT, HELP, ACTION
	};

	public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
		String servletName = getInitParameter(parameterName);
		response.setContentType("text/html");
		if (request.getAttribute(modeParameter) == null) {
			request.setAttribute(modeParameter, modes.VIEW);
		}
		getPortletContext().getRequestDispatcher("/" + servletName).include(request, response);
	}

	public void doEdit(RenderRequest request, RenderResponse response) throws PortletException, IOException {
		request.setAttribute(modeParameter, modes.EDIT);
		doView(request, response);
	}

	public void doHelp(RenderRequest request, RenderResponse response) throws PortletException, IOException {
		request.setAttribute(modeParameter, modes.HELP);
		doView(request, response);
	}

	public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException {
		request.setAttribute(modeParameter, modes.ACTION);
		String servletName = getInitParameter(parameterName);
		getPortletContext().getRequestDispatcher("/" + servletName).include(request, response);
	}
}


@WebServlet(urlPatterns = { "/EmotionServlet" })
public class EmotionServlet extends HttpServlet {
	private static final long	serialVersionUID	= 1L;

	@PersistenceContext(unitName = "default")
	EntityManager				manager;

	@EJB
	EmotionEJB					ejb;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String actionUrl = ((RenderResponse) request.getAttribute("javax.portlet.response")).createActionURL().toString();
		try {
			List<emotion> ems = manager.createQuery(manager.getCriteriaBuilder().createQuery(Emotion.class)).getResultList();
			int pos = 5;
			if (ems.size() != 0) {
				pos = ems.get(0).getPosition();
			}
			response.getWriter().write("<span><form method="\&quot;POST\&quot;" action="\&quot;&quot;" + actionUrl "\"><input type="\&quot;hidden\&quot;" name="\&quot;vote\&quot;" value="\&quot;minus\&quot;"><input type="\&quot;submit\&quot;" value="\&quot;-\&quot;"></form>TEST:" + pos + "<form method="\&quot;POST\&quot;" action="\&quot;&quot;" + actionUrl "\"><input type="\&quot;hidden\&quot;" name="\&quot;vote\&quot;" value="\&quot;plus\&quot;"><input type="\&quot;submit\&quot;" value="\&quot;+\&quot;"></form></span>");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		boolean up = true;
		String param = request.getParameter("vote");
		if (param == null) {
			return;
		}
		if (param.compareTo("minus") == 0) {
			up = false;
		}
		ejb.modifyEmotion(up);
	}

}</emotion>


@LocalBean
@Stateless
public class EmotionEJB {

	@PersistenceContext(unitName = "default")
	EntityManager	manager;

	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void modifyEmotion(boolean up) {
		int lastPos = 5;
		for (Emotion e : manager.createQuery(manager.getCriteriaBuilder().createQuery(Emotion.class)).getResultList()) {
			lastPos = e.getPosition();
			manager.remove(e);
		}
		Emotion e = new Emotion();
		e.setPosition(Math.min(Math.max(lastPos + (up ? 1 : -1), 1), 10));
		manager.persist(e);
	}

}


+Az entitás, az már nem annyira fontos.

Remélem ez az írás tud majd segíteni olyannak, aki hasonló cipőben jár. Még majd annyival lehet bővíteni, hogy a GET-es action-öket is lekezelje, mert most csak POST-ra működik.
thumbnail
Rix Beck,修改在14 年前。

RE: Portlet + annotációk

Junior Member 帖子: 95 加入日期: 09-11-9 最近的帖子
Hasznos infó. Gondolom mindannyiunknak vannak már "kész" servletjei, amit kár szétbombázni.

köszi
Vilmos Papp,修改在3 个月前。

RE: Portlet + annotációk

Regular Member 帖子: 131 加入日期: 09-5-4 最近的帖子
Mivel mi maradtunk a standard Liferay-es megoldásoknál (ServiceBuilder, Hibernate, stb.) még szerencsére nem futottam bele ebbe, de jó, hogy van rá workaround :-)

Köszi!