PDA

View Full Version : نمونه سازی از stateful session bean



ar.mahdian
شنبه 15 آبان 1389, 16:25 عصر
با سلام
سوال من در مورد stateful session bean است.
من به تازگی درگیر این تکنولوژی شدم و با کتابهایی که دم دستم بود شروع کردم.
یه مثال کلاسیک در مورد stateful session bean در اکثر کتابها هست که معروفه به shoping cart.
لینک (http://docs.sun.com/app/docs/doc/819-3669/bnboc?l=en&a=view)
این مثال رو نوشتم و همونطور که باید کار میکنه اما...
توی کلاس مربوط به bean یک متدی هست که با Remove@ علامتگذاری شده٬ یعنی هروقت اینو فراخوانی کردم شیء ساخته شده را نابود کن. تا اینجا مشکلی نیست٬ اما اگر بخوام دوباره یه شیء دیگه بسازم گیر میده
من کلاینت رو از نوع سرولت انتخاب کردم و از رفرنس لوکال bean استفاده کردم.
وقتی سرولت رو اجرا میکنم جواب میده اما اگر اونو رفرش کنم میگه که شیء وجود نداره یعنی وقتی شیء یک بار تخریب شد دیگه نمیتونه دوباره بسازه مگه اینکه دوباره پروژه رو از نتبینز ران کنم.
تا فراموش نکردم بگم که من از نتبینز 6.9 و گلسفیش استفاده میکنم.

پیغام خطا:


SEVERE: NRU-myPack.CartBean: Cannot load from BACKUPSTORE FOR Key: <907f0100001f-2154fd94-0>


javax.ejb.NoSuchObjectLocalException: The EJB does not exist. session-key: 907f0100001f-2154fd94-0

یه نفر دیگه هم به این مشکل برخورد کرده بود... لینک (http://www.coderanch.com/t/320171/EJB-JEE/java/Stateful-session-bean-Remove-EJB)

مشکل از کجاست؟

javaphantom
یک شنبه 16 آبان 1389, 00:10 صبح
با سلام
سوال من در مورد stateful session bean است.
من به تازگی درگیر این تکنولوژی شدم و با کتابهایی که دم دستم بود شروع کردم.
یه مثال کلاسیک در مورد stateful session bean در اکثر کتابها هست که معروفه به shoping cart.
لینک (http://docs.sun.com/app/docs/doc/819-3669/bnboc?l=en&a=view)
این مثال رو نوشتم و همونطور که باید کار میکنه اما...
توی کلاس مربوط به bean یک متدی هست که با Remove@ علامتگذاری شده٬ یعنی هروقت اینو فراخوانی کردم شیء ساخته شده را نابود کن. تا اینجا مشکلی نیست٬ اما اگر بخوام دوباره یه شیء دیگه بسازم گیر میده
من کلاینت رو از نوع سرولت انتخاب کردم و از رفرنس لوکال bean استفاده کردم.
وقتی سرولت رو اجرا میکنم جواب میده اما اگر اونو رفرش کنم میگه که شیء وجود نداره یعنی وقتی شیء یک بار تخریب شد دیگه نمیتونه دوباره بسازه مگه اینکه دوباره پروژه رو از نتبینز ران کنم.
تا فراموش نکردم بگم که من از نتبینز 6.9 و گلسفیش استفاده میکنم.

پیغام خطا:


SEVERE: NRU-myPack.CartBean: Cannot load from BACKUPSTORE FOR Key: <907f0100001f-2154fd94-0>


javax.ejb.NoSuchObjectLocalException: The EJB does not exist. session-key: 907f0100001f-2154fd94-0

یه نفر دیگه هم به این مشکل برخورد کرده بود... لینک (http://www.coderanch.com/t/320171/EJB-JEE/java/Stateful-session-bean-Remove-EJB)

مشکل از کجاست؟

شما وقتی Remove@ می کنی یعنی کلا از حافظه برش می داری یعنی کلا دیگه objectی وجود نداره. برای همین هست که دیگه کارتمام شده.
باید دوباره lookup یا inject کنی. من مطمعن نیستم ولی فردا جواب قطعی رو بهت می دم.
در ضمن با spring یک سعی بکنم. جواب می ده. نمی دونم اون چه جوری پیاده سازی کرده.

javaphantom
یک شنبه 16 آبان 1389, 08:47 صبح
دقیقا همانطور که در پست قبلی اشاره کردم وقتی شما remove کردی اون session رو از حافظه پاک کردی پس باید یک بار دیگه یک session درست کنی یعنی از توی container بیایی lookup کنی یا inject توی این مثال که برات فرستادم عملی می بینی که کار می کنه.
از stub ی به نام openejb استفاده کردم تا سریع test و deploy کنم.


@Local
public interface CountBiz {

public int count() throws Exception;

public void set(int value) throws Exception;

public void remove() throws Exception;
}



public class CountCallBacks {

@PostConstruct
public void construct(InvocationContext ctx) {
System.out.println("constructor");
}

@PostActivate
public void activate(InvocationContext ctx) {
System.out.println("activate");
}

@PrePassivate
public void passivate(InvocationContext ctx) {
System.out.println("passivate");
}

@PreDestroy
public void destroy(InvocationContext ctx) {
System.out.println("destroy");
}
}



@Local(CountBiz.class)
@Stateful
@Interceptors(CountCallBacks.class)
public class CountBizImpl implements CountBiz {

private int value;

public int count() throws Exception {
return ++value;
}

public void set(int value) throws Exception {
this.value = value;
}

@Remove
public void remove() throws Exception {
System.out.println("remove");
}
}

با JUnit تست نوشتم دقت کن


public class CountBizImplTest {

private CountBiz countBix;
private InitialContext context;

@Before
public void setUp() {
Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FAC TORY, "org.apache.openejb.client.LocalInitialContextFacto ry");

try {
context = new InitialContext(properties);
countBix = (CountBiz) context.lookup("CountBizImplLocal");
} catch (NamingException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}

@Test
public void testBean() throws Exception {
int i = countBix.count();
System.out.println("i = " + i);
countBix.set(50);
System.out.println("countBix.count() = " + countBix.count());
countBix.remove();

countBix = (CountBiz) context.lookup("CountBizImplLocal");
Assert.assertNotNull(countBix);
System.out.println("countBix.count() = " + countBix.count());
}

@Test(expected = Exception.class)
public void testBeanForNull() throws Exception {
int i = countBix.count();
System.out.println("i = " + i);
countBix.set(50);
System.out.println("countBix.count() = " + countBix.count());
countBix.remove();
countBix.count();
}

}

ar.mahdian
یک شنبه 16 آبان 1389, 19:47 عصر
خیلی ممنونم که جواب دادید.
راستشو بخواید خودمم حدس میزدم که باید دوباره یه شیء جدید بسازم اما هر چه تلاش کردم نشد. جستجو هم کرد اما چیزی پیدا نکردم.
شما ار مواردی استفاده کردید که من تازه کار هنوز بلد نشدم مثل junit و stub.(البته بعدا میرم سراغشون)
من کد برنامه رو اینجا میگزارم. اگه ممکنه این کد رو تغییر بدید.
کد اینترفیس:

@Local
public interface CartBeanLocal {

void addBook(String title);

List<String> getContents();

void initialize();

boolean removeBook(String title);

void del();
}

کد کلاس بین:


@Stateful
public class CartBean implements CartBeanLocal {

List<String> contents;

@PostConstruct
public void initialize() {
System.out.println("Hi- i am created.");
contents = new ArrayList<String>();
}

public void addBook(String title) {
System.out.println("Hi- adding book:"+title);
contents.add(title);
}

public boolean removeBook(String title) {
System.out.println("Hi- removing book:"+title);
return contents.remove(title);

}

public List<String> getContents() {
System.out.println("Hi- return contents");
return contents;
}

@Remove
public void del(){
System.out.println("Bye .");
contents = null;
}

}

بخشی از کد سرولت:

@EJB
private CartBeanLocal cartBean;

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = null;
out = response.getWriter();


out.println("<html>");
out.println("<head>");
out.println("<title>Servlet Servlet1</title>");
out.println("</head>");
out.println("<body>");

cartBean.addBook("book1");
cartBean.addBook("book2");
cartBean.addBook("book3");

printAll(out);
out.println("<hr>");
cartBean.removeBook("book1");

printAll(out);

cartBean.del();

out.println("</body>");
out.println("</html>");
out.close();
}
private void printAll(PrintWriter out) {

List<String> bookList = cartBean.getContents();

Iterator<String> iterator = bookList.iterator();

while (iterator.hasNext()) {
String title = iterator.next();

out.println("<h2>Retrieving book title from cart: " + title + "</h2>");
}


این برنامه بدون هیچ مشکلی اجرا میشه اما اگر رفرش کنم ارور میده.
البته دلیلش رو اشاره کردید اگر ممکنه راه حلش رو برای این کد هم اشاره کنید.
در واقع میخوام هر بار که postback رخ میده یک شیء از bean تعریف شده ساخته بشه و کار ما رو انجام بده و در انتها تخریب بشه. همین!

javaphantom
دوشنبه 17 آبان 1389, 13:20 عصر
نکته وقتی شما نمی توانید روی چند thread عمل Injection رو انجام بدید.

Injection یعنی همین عملی که شما EJB@ بالای فیلد CartBean گذاشتین یعنی به container گفتین برای من عمل Instantiate یا هما new کردن رو انجام بده.

راه حل: باید از طریق loopkup کردن object رو بیارید. کدش رو براتون نوشتم. قبلش jar فایل appserver-rt.jar رو به classpath تون اضافه کنید.

البته اگر دارید با glassfish کار می کنید که چون گفتید با netbeans دارید کار می کنید 100% با glassfish هست.

من یک سری تغییرات کوچکم توی کل برنامه دادم در نتیجه کل کد براتون می زام.

برنامه بدون هیچ مشکلی کار می کنه.


public interface CartBeanLocal {

void addBook(String title);

List<String> getContents();

void initialize();

boolean removeBook(String title);

void del();
}


@Stateful(mappedName = "b")
@Remote(CartBeanLocal.class)
public class CartBean implements CartBeanLocal {

List<String> contents;

@PostConstruct
public void initialize() {
System.out.println("Hi- i am created.");
contents = new ArrayList<String>();
}

public void addBook(String title) {
System.out.println("Hi- adding book:" + title);
contents.add(title);
}

public boolean removeBook(String title) {
System.out.println("Hi- removing book:" + title);
return contents.remove(title);

}

public List<String> getContents() {
System.out.println("Hi- return contents");
return contents;
}

@Remove
public void del() {
System.out.println("Bye .");
contents = null;
}

}


public class MyServlet extends HttpServlet {

private CartBeanLocal cartBean;


private InitialContext context;

private void instanceCartBean() {
Properties prop = new Properties();
prop.setProperty("java.naming.factory.initial",
"com.sun.enterprise.naming.SerialInitContextFactory");
prop.setProperty("java.naming.factory.url.pkgs",
"com.sun.enterprise.naming");
prop.setProperty("java.naming.factory.state",
"com.sun.corba.ee.impl.presentation.rmi.JNDIStateFa ctoryImpl");

prop.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");

prop.setProperty("org.omg.CORBA.ORBInitialPort", "3700");

try {
this.context = new InitialContext(prop);
this.cartBean = (CartBeanLocal) context.lookup("b");
} catch (NamingException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}

}


@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.instanceCartBean();

response.setContentType("text/html;charset=UTF-8");
PrintWriter out = null;
out = response.getWriter();

out.println("<html>");
out.println("<head>");
out.println("<title>Servlet Servlet1</title>");
out.println("</head>");
out.println("<body>");

cartBean.addBook("book1");
cartBean.addBook("book2");
cartBean.addBook("book3");

printAll(out);
out.println("<hr>");
cartBean.removeBook("book1");

printAll(out);

cartBean.del();

out.println("</body>");
out.println("</html>");
out.close();
}

private void printAll(PrintWriter out) {

List<String> bookList = cartBean.getContents();

Iterator<String> iterator = bookList.iterator();

while (iterator.hasNext()) {
String title = iterator.next();

out.println("<h2>Retrieving book title from cart: " + title + "</h2>");
}
}
}