JavaBlog.fr / Java.lu DEVELOPMENT,Documentum,Java Documentum : BOF – SBO (Service based Business Object) – NoSuchMethodException – JAVA reflection

Documentum : BOF – SBO (Service based Business Object) – NoSuchMethodException – JAVA reflection

Hello,

After my previous post http://www.javablog.fr/documentum-bof-sbo-service-based-business-object-tbo-type-based-business-object-aspects.html, just a mini post related an error java.lang.NoSuchMethodException which occurs when the use of a SBO’s method whereas it exists. Basically in JAVA, the problem seems concern the type of POJO’s argument used between the SBO and the SBO’s client (like DCTM JOB…), the package or attributes could be different.

01// ERROR CASE
02try {
03IDfService dfService = DfClient.getLocalClientEx().newService("com.huo.lu.business.sbo.ecm.mail.IMailSBO", session.getSessionManager());
04 
05Method method = dfService.getClass().getMethod("sendMail", com.huo.lu.business.sbo.ecm.mail.Mail.class);
06 
07method.invoke(dfService, mailMessage);
08 
09} catch (Exception e) {
10throw new DfException(MessageFormat.format("MailSBO.sendMail({0}, {1})", session, mailMessage), e);
11}
12 
13....Caused by: java.lang.NoSuchMethodException: com.huo.lu.business.sbo.ecm.mail.impl.MailSBO.sendMail(com.huo.lu.business.sbo.ecm.mail.Mail)
14at java.lang.Class.getMethod(Class.java:1624)
15... 23 more

This error doesn’t concern the presence or not of “serialVersionUID” attribute in a POJO.The Serial Version ID is used when serializing and deserializing an object. Java recognizes if the bytes you want to deserialize match the local class version. If not it will throw an exception. This is important when doing RMI or persisting object structures.

1private static final long serialVersionUID = 6512673270706929264L;

However, this error occurs even with a local POJO class totally identical with the POJO class version in SBO (same package, same source), so, a simple solution is the adding of JAR containing the POJO used in SBO in the CLIENT side. Another solution is the use of class loader of remote SBO when the method is loaded/retrieved with the use of JAVA reflection for instantiation for given REMOTE POJO classes.

1// #### OLD : ERROR CASE
2Method method = dfService.getClass().getMethod("sendMail", com.huo.lu.business.sbo.ecm.mail.Mail.class);
3 
4// #### NEW : with use of SBO class loader
5Method method = dfService.getClass().getMethod("sendMail", dfService.getClass().getClassLoader().loadClass("com.huo.lu.business.sbo.ecm.mail.Mail"));

Here, a full example using the SBO class loader and JAVA reflection.
So, the local POJO classes (InternetAddress / Mail) are NOT necessary:

01package com.huo.lu.business.sbo.ecm.mail;
02 
03// ... import
04 
05public class InternetAddress {
06private String label;
07private String address;
08public InternetAddress() {
09this(null, null);
10}
11 
12// .... GETTERS / SETTERS
13}
01package com.huo.lu.business.sbo.ecm.mail;
02 
03// ... import
04 
05public class Mail {
06 
07private InternetAddress from;
08private List<InternetAddress> to;
09private List<InternetAddress> cc;
10private List<InternetAddress> bcc;
11private String subject;
12private String body;
13 
14public Mail() {
15}
16 
17// .... GETTERS / SETTERS
18}
01IDfService dfService = DfClient.getLocalClientEx().newService("com.huo.lu.business.sbo.ecm.mail.IMailSBO", session.getSessionManager());
02 
03ClassLoader classLoaderOfRemoteService = dfService.getClass().getClassLoader();
04 
05Class<?> clazzMail = classLoaderOfRemoteService.loadClass("com.huo.lu.business.sbo.ecm.mail.Mail");
06 
07Class<?> clazzInternetAddress = classLoaderOfRemoteService.loadClass("com.huo.lu.business.sbo.ecm.mail.InternetAddress");
08 
09Mail objectMail = new Mail();
10objectMail = clazzMail.newInstance();
11 
12// # setFrom(InternetAddress from)
13// objectMail.setFrom(new InternetAddress(SENDER_EMAIL, SENDER_FRIENDLYNAME));
14{
15// InternetAddress
16Constructor<?> constructorInternetAddress = clazzInternetAddress.getConstructor(new Class[] { String.class, String.class});
17Object objectInternetAddress = constructorInternetAddress.newInstance(new Object[] { SENDER_EMAIL, SENDER_FRIENDLYNAME });
18Method methodSetFrom = objectMail.getClass().getMethod("setFrom", clazzInternetAddress);
19methodSetFrom.invoke(objectMail, objectInternetAddress);
20}
21 
22// # setTo(List<InternetAddress> to)
23// objectMail.setTo(emailAssignees);
24{
25List<Object> listOfAssigneesInternetAddress = new ArrayList<Object>();
26for (Iterator<String> emailAssigneesIter = emailAssignees.iterator(); emailAssigneesIter.hasNext();) {
27String emailAssigneeStr = emailAssigneesIter.next();
28// InternetAddress
29Constructor<?> constructorInternetAddress = clazzInternetAddress.getConstructor(new Class[] { String.class});
30Object objectInternetAddress = constructorInternetAddress.newInstance(new Object[] { emailAssigneeStr });
31listOfAssigneesInternetAddress.add(objectInternetAddress);
32}//end-for
33 
34Method methodSetTo = objectMail.getClass().getMethod("setTo", List.class);
35methodSetTo.invoke(objectMail, listOfAssigneesInternetAddress);
36}
37 
38// # setSubject(String subject)
39// objectMail.setSubject("SUBJECT 123");
40{
41Method methodSetSubject = objectMail.getClass().getMethod("setSubject", String.class);
42methodSetSubject.invoke(objectMail, "SUBJECT 123");
43}
44 
45// # setBody(String body)
46// objectMail.setBody(createMailBody());
47{
48Method methodSetBody = objectMail.getClass().getMethod("setBody", String.class);
49methodSetBody.invoke(objectMail, createMailBody());
50}
51 
52Method method = dfService.getClass().getMethod("sendMail", clazzMail);
53method.invoke(dfService, objectMail);

Best regards

Huseyin OZVEREN

Leave a Reply

Your email address will not be published.

Time limit is exhausted. Please reload CAPTCHA.

Related Post