留言板
Portlet + annotációk
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:
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?
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="\"POST\"" action="\""" + response.createActionURL() "\"><input type="\"hidden\"" name="\"vote\"" value="\"minus\""><input type="\"submit\"" value="\"-\""></form>TEST:" + pos + "<form method="\"POST\"" action="\""" + response.createActionURL() "\"><input type="\"hidden\"" name="\"vote\"" value="\"plus\""><input type="\"submit\"" value="\"+\""></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?
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:
+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.
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="\"POST\"" action="\""" + actionUrl "\"><input type="\"hidden\"" name="\"vote\"" value="\"minus\""><input type="\"submit\"" value="\"-\""></form>TEST:" + pos + "<form method="\"POST\"" action="\""" + actionUrl "\"><input type="\"hidden\"" name="\"vote\"" value="\"plus\""><input type="\"submit\"" value="\"+\""></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.