A portlet egyszerű adatbáziskezelést valósít meg, elneveztem EmotionMeterPortletnek. A funkcionalitási kimerül abban, hogy egy 1-10 közé eső értéket megmutat, és ad 2 gombot, amelyekkel le vagy felfelé piszkálhatjuk, az aktuális értéket pedig adatbázisba teszi.
Telepítések
Szükségünk lesz egy Glassfish-re, Eclipse-re, valamint a Liferay-re, meg egy választott adatbáziskezelőre (esetemben ez MySql, de lehetne bármilyen más relációs is).
Glassfish telepítése: Töltsük le a v3 Web profilt (tölthetjük a teljeset is), telepítsük fel valahova, az alaéprtelmezett beállítások általában jók, én a java elérési utat állítottam csak át.
Eclipse telepítése: Töltsünk egy EE-s Eclipse-t, opcionálisan tegyük fel a Portal Pack-ot (https://eclipse-portalpack.dev.java.net/install.html), valamint a Glassfish adaptert. Ubuntu-n az Eclipse fagyások elkerülésére ki kellett kapcsolni az Assistive Technologiest(+relogin).
Liferay telepítése: Szükségünk lesz a liferay war-os változatára, valamint a dependenciákra. Az utóbbit bontsuk ki a Glassfish lib-jébe, az előbbit meg majd telepítsük az AS-be.
Egyebek telepítése: Szükségünk lesz egy XML parserre, ehhez töltsük le a Xerxes-t (http://www.apache.org/dist/xerces/j/), é saf az xml-apis, xerxesImpl, serializer és resolver jarokat tegyük a lib-be. Szükséges még egy JPA provider telepítése is, esetemben ez az EclipseLink lesz. Töltsük le, és az eclipselink és jpa2-es jarokat tegyük a lib-be. Végül az adatbázisunknak megfelelő connector-t is tegyük be a többi jar közé.
Beállítások
Érdemes a fejlesztéshez a Liferay development módot bekapcsolni. Ehhez a domain.xml-be kell egy új jvm opciót felvenni, tehát szúrjuk be az alábbi sort a megfelelő helyre:
-Dexternal-properties=portal-developer.properties
Ezután indítsuk el az AS-t, telepítsük a liferay.war-t, állítsuk be alapértelmezett web modulnak a virtuális szerveren, valamint vegyünk fel egy JDBC Connection Pool-t és Resource-t. Én ezt jdbc/emotion név alá tettem.
Beállítások
Érdemes a fejlesztéshez a Liferay development módot bekapcsolni. Ehhez a domain.xml-be kell egy új jvm opciót felvenni, tehát szúrjuk be az alábbi sort a megfelelő helyre:
Ezután indítsuk el az AS-t, telepítsük a liferay.war-t, állítsuk be alapértelmezett web modulnak a virtuális szerveren, valamint vegyünk fel egy JDBC Connection Pool-t és Resource-t. Én ezt jdbc/emotion név alá tettem.
Portlet fejlesztése
Hozzunk létre egy új projectet Eclipse-ben, ha fent van a Portal Pack, akkor a Dynamic Web Projectnél válasszük ki a Portlet 2.0-ás konfigurációt, ekkor létre gof hozni néhány szükséges fájlt magától.
Összesen 8 fájlt kell megírnunk.
WebContent/WEB-INF/portlet.xml: Ide kerülnek a portletet leíró beállítások.
<?xml version='1.0' encoding='UTF-8' ?>
<portlet-app xmlns='http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:schemaLocation='http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd'
version='2.0'>
<portlet>
<description>EmotionMeterPortlet</description>
<portlet-name>EmotionMeterPortlet</portlet-name>
<display-name>EmotionMeterPortlet</display-name>
<portlet-class>hu.test.BaseRedirectorPortlet</portlet-class>
<init-param>
<name>target-servlet</name>
<value>EmotionServlet</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
<portlet-mode>EDIT</portlet-mode>
<portlet-mode>HELP</portlet-mode>
</supports>
<resource-bundle>hu.test.Language</resource-bundle>
<portlet-info>
<title>EmotionMeterPortlet</title>
<short-title>EmotionMeterPortlet</short-title>
</portlet-info>
<security-role-ref>
<role-name>administrator</role-name>
</security-role-ref>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
</portlet>
</portlet-app>WebContent/WEB-INF/liferay-portlet.xml: Ide a Liferay egyedi beállításai kerülnek.<?xml version="1.0"?>
<!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 4.2.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_4_2_0.dtd">
<liferay-portlet-app>
<portlet>
<portlet-name>EmotionMeterPortlet</portlet-name>
<instanceable>true</instanceable>
</portlet>
<role-mapper>
<role-name>administrator</role-name>
<role-link>Administrator</role-link>
</role-mapper>
<role-mapper>
<role-name>guest</role-name>
<role-link>Guest</role-link>
</role-mapper>
<role-mapper>
<role-name>power-user</role-name>
<role-link>Power User</role-link>
</role-mapper>
<role-mapper>
<role-name>user</role-name>
<role-link>User</role-link>
</role-mapper>
</liferay-portlet-app>WebContent/WEB-INF/liferay-display.xml: Ide a Liferay portlet megjelenítését szabályozó beállítások kerülnek:<?xml version="1.0"?>
<!DOCTYPE display PUBLIC "-//Liferay//DTD Display 5.2.0//EN" "http://www.liferay.com/dtd/liferay-display_5_2_0.dtd">
<display>
<category name="category.emotion">
<portlet id="EmotionMeterPortlet" />
</category>
</display>src/META-INF/persistence.xml: Magáért beszél, figyeljünk arra, hogy az src-n belül létre kell hoznunk ezt a könyvtárat.<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="default" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/emotion</jta-data-source>
<properties>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
</properties>
</persistence-unit>
</persistence>src/hu/test/Language.properties: A nyelvi beállítások vannak benne.javax.portlet.title.EmotionMeterPortlet=EmotionMeter Portlet
category.emotion=Emotion
src/hu/test/BaseRedirectorPortlet.java: Ez egy általános portlet, mely egy megadott szervletre irányítja tovább a kérést. Mivel a portlet feldolgozása közben nincsen CDI (nem tudom, hogy miért, de nincsen), szervleteknél viszont van, ezért átirányítjuk a kérést, és utána dolgozzuk fel./** 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);
}
}src/hu/test/EmotionServlet.java: Ide kerül a portlet logikája.@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);
}
}src/hu/test/EmotionEJB.java: A CMP-hez szükséges ez az EJB.@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);
}
}src/hu/test/entities/Emotion.java: Az entitás.@Entity
public class Emotion implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private int position;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
}Portlet telepítéseA portlet elkészítése után szeretnénk kitelepíteni. Az Eclipse-s deploy megoldás sajnos nem alkalmazható, mivel az nem futtat le Liferay-specifikus eseményeket, ezért a Liferay autodeploy funkcióját fogjuk használni. Mivel kényelmetlen minden buildelés után másolgatni, ezért érdemes ezt automatizálni. Ebben segít ez a build.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="EmotionMeterPortlet" basedir=".">
<property name="warfile" value="EmotionMeterPortlet" />
<property name="deploy.dir" value="/home/sashee/glassfishv3/deploy"/>
<target name="create">
<war destfile="${warfile}.war" webxml="WebContent/WEB-INF/web.xml"
update="true" compress="false">
<classes dir="build\classes" />
<fileset dir="WebContent">
<exclude name="WEB-INF/web.xml" />
</fileset>
</war>
</target>
<target name="copy">
<copy todir="${deploy.dir}" overwrite="true">
<fileset dir=".">
<include name="*.war" />
</fileset>
</copy>
</target>
<target name="deploy">
<antcall target="create" />
<antcall target="copy" />
</target>
</project>Természetesen az elérési utat írjuk át használat előtt. Eclipse-ben beállíthatjuk ezt a project builderei közé, és akkor minden mentés (vagy buildelés) után magától ki is fogja telepíteni a változtatásokat. Érdemes a Liferay-en belül a check interval-t levenni 5s-re, valamint Eclipse-ben az Allocate Console-t kivenni, hogy ne ugorjon el minden mentésnél.Ezzel készen is vagyunk, van egy egyszerű portletünk, valamint be van lőve egy hatékony fejlesztői környezet is. Sajnos az exploded deploymentet nem tudjuk használni így, azonban a mentéstől számított kitelepítés 4-5 másodperc nálam, ez elfogadható. Bár azt nem próbáltam, de elvileg az állapot is megmarad.
Nincsenek megjegyzések:
Megjegyzés küldése