我有一个内容导航器插件,我需要通过该插件发送电子邮件。插件已部署在WebSphere中,以下是我遵循的步骤。
- 在WAS 中创建了一个邮件提供商
- 创建了邮件会议,然后选择" SMTP"作为协议
我有一个Java代码,该代码发送电子邮件
Context context = new InitialContext();
Session mailSession = (Session)context.lookup("mail/mySession");
Message msg = new MimeMessage(mailSession);
msg.setFrom(new InternetAddress(email)); msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(destinationAddress));
// Set the subject and body text
msg.setSubject(subject);
msg.setText(messageBody);
// send message
Transport.send(msg);
我会遇到错误作为
java.lang.ClassCastException: javax.mail.Session incompatible with javax.mail.Session
我的webpshere(c: ibm websphere appserver lib(默认情况下具有mailapi.jar。甚至Navigator.war和Taskmanagerweb.war也有相同的罐子。我认为问题是由于在同一WebSphere中具有多个罐子。谁能帮助我解决这个问题?
由于WebSphere是Java EE产品,因此它应该包含完整的Javamail实现。您不需要在应用程序中包含任何Javamail Jar文件。
已经有一段时间了,但是我很久以前就遇到了同样的问题。我终于得出的结论是,导航器包括其自己的javax.mail-当您的插件由临时导航器创建的parent-last class Loader加载时,它将无法匹配ee javax.mail.mail.mail.sessions。javax.mail.Sessess由插件classloader找到。
我建议以下两个解决方案之一:
- 在导航器插件之外移动邮件功能。例如。创建执行您功能的EJB,并在插件注入/查找ejb中。
- 使用导航器邮件会话而不是WebSphere邮件会议。
另外两个替代方案:
-
不要进行打字并使用反射。我不确定是否可以使用错误的类找到正确的模拟模仿构造函数。
-
使用代码模块从CPE发送电子邮件。虽然您描述的问题实际上也适用于CPE,但它可以选择使用PE配置或CE配置的邮件会话。
您可以配置cnmail以使用Java邮件,但它无法与Office 365和Modern Authentication一起使用。我打开了一张支持票,询问是否有开箱即用的解决方案,而IBM的完整且完整的答复如下:
'没有开箱即用的解决方案。
Microsoft确实报告了JavaScript和Java库,以支持可能支持插件的现代身份验证。其他选项是禁用菜单项,然后用户必须手动下载并附加到电子邮件。这是链接WRT Modern Auth和JavaScript/Java:
https://devblogs.microsoft.com/microsoft365dev/microsoft-authentication-libraries-for-java-and-python-python-are-are-now-now-generally-available/
以下代码可能会为您提供帮助。请注意,我评论了代码以帮助您使用解决方案。
**- **RecoveryBin.js****
require([ "dojo/_base/declare", "dojo/_base/lang", "ecm/model/Request",
"ecm/model/ResultSet", "recoveryBeanDojo/BestDialog",
"ecm/widget/ComboBox", "dojo/domReady!" ], function(declare, lang,
Request, ResultSet, BestDialog, ComboBox) {
/**
* Use this function to add any global JavaScript methods your plug-in requires.
*/
lang.setObject("moveToRB", function(repository, items, callback, teamspace,
resultSet, parameterMap) {
/*
* Add custom code for your action here. For example, your action might launch a dialog or call a plug-in service.
*/
// Iterating items array --- {d0c1},{doc2}
var itemsList="";
console.log("Number of selected documents -- "+ items.length);
for(var j=0;j<items.length;j++)
{
itemsList=itemsList+items[j].id+",";
console.log("Item is --"+itemsList);
}
console.log("New Items String is ---- "+itemsList);
var bestDialog = null;
var serviceParams = {
icnRepository : repository.id,
serverType : repository.type,
// s : items[0].id,
s : itemsList,
};
Request.invokePluginService("RecoveryBean", "MoveToRBService", {
requestParams : serviceParams,
requestCompleteCallback : lang.hitch(this, function(response) {
var rb;
for (var i = 0; i < response.rb.length; i++) {
rb = response.rb[i];
}// success*/
console.log("Before New Dialog ");
bestDialog = new BestDialog();
//bestDialog.setContentItem(items[0]);
bestDialog._show(rb, repository, items);
bestDialog.show();
console.log("After bin Dialog");
})
});
});
});
**
- BestDialog.js
**
define([ "dojo/_base/declare", "ecm/widget/dialog/BaseDialog",
"dijit/form/CurrencyTextBox", "dojo/currency", "ecm/model/ContentItem",
"dojo/store/Memory", "ecm/model/Request", "ecm/model/ResultSet",
"dijit/layout/ContentPane", "dojo/dom-attr",
"ecm/widget/layout/_RepositorySelectorMixin",
"ecm/widget/listView/ContentList", "ecm/model/Desktop",
"dojo/_base/lang", "ecm/widget/ComboBox",
"dojo/text!./templates/BestDialog.html" ], function(declare,
BaseDialog, CurrencyTextBox, currency, ContentItem, MemoryStore,
Request, ResultSet, ContentPane, domAttr, _RepositorySelectorMixin,
ContentList, Desktop, lang, ComboBox, template) {
/**
* @name sampleICNPluginDojo.BestDialog
* @class Provides a dialog that demonstrates the right thing to do.
* @augments ecm.widget.BaseDialog
*/
return declare("newPluginDojo.BestDialog", [ BaseDialog ], {
/** @lends sampleICNPluginDojo.BestDialog.prototype */
contentString : template,
widgetsInTemplate : true,
contentItem : null,
_repository : null,
_items : null,
itemsList:null,
_binlist : null,
postCreate : function() {
console.log("Inside BestDialog.js:: postCreate ");
this.inherited(arguments);
this.setTitle("Recovery - Beans");
this.okButton = this.addButton("Ok", "_okClick", false, true);
},
_okClick : function() {
console.log("Inside BestDialog.js:: _okClick ");
var n = this._binlist.value;
var serviceParams = {
icnRepository : this._repository.id,
serverType : this._repository.type,
s : this.itemsList,
rbName : n
};
Request.invokePluginService("RecoveryBean", "RecoveryService", {
requestParams : serviceParams,
requestCompleteCallback : lang.hitch(this, function(response) {
var bestDialog = new BaseDialog();
bestDialog.set("title", "Deleted Items Bean");
bestDialog.set("content","Document Are Successfully Moved To Recycle Bin");
bestDialog.show();
console.log("After Recovery Service Dialog");
})
});
this.hide();
this.destroyRecursive(); // Destroys all child widgets as well
},
onCancel : function() {
this.destroyRecursive();
},
// Method responsible to show dialog box:- Documented by Ashok
_show : function(rb, repository, items) {
console.log("inside show ");
this._repository = repository;
this._items = items;
this._rb = rb;
var item = [];
for ( var key in rb) {
item.push({
"id" : rb[key],
"name" : key
});
console.log(key + ":" + rb[key]);
}
// Create test store.
comboStore = new MemoryStore({
data : item
});
this._binlist = this.binlist;
this._binlist.store = comboStore;
console.log("Completed");
}
});
});
**MoveToRBService.java**
package com.ibm.demo;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import javax.security.auth.Subject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.filenet.api.collection.CmRecoveryItemSet;
import com.filenet.api.collection.EventSet;
import com.filenet.api.collection.IndependentObjectSet;
import com.filenet.api.constants.RefreshMode;
import com.filenet.api.core.Document;
import com.filenet.api.core.Factory;
import com.filenet.api.core.ObjectStore;
import com.filenet.api.core.VersionSeries;
import com.filenet.api.events.Event;
import com.filenet.api.query.SearchSQL;
import com.filenet.api.query.SearchScope;
import com.filenet.api.util.CmRecoveryBin;
import com.filenet.api.util.CmRecoveryItem;
import com.filenet.api.util.Id;
import com.filenet.api.util.UserContext;
import com.ibm.ecm.extension.PluginResponseUtil;
import com.ibm.ecm.extension.PluginService;
import com.ibm.ecm.extension.PluginServiceCallbacks;
import com.ibm.ecm.json.JSONMessage;
import com.ibm.ecm.json.JSONResponse;
import com.ibm.ecm.json.JSONResultSetResponse;
import com.ibm.json.java.JSONArray;
import com.ibm.json.java.JSONObject;
/**
* Provides an abstract class that is extended to create a class implementing
* each service provided by the plug-in. Services are actions, similar to
* servlets or Struts actions, that perform operations on the IBM Content
* Navigator server. A service can access content server application programming
* interfaces (APIs) and Java EE APIs.
* <p>
* Services are invoked from the JavaScript functions that are defined for the
* plug-in by using the <code>ecm.model.Request.invokePluginService</code>
* function.
* </p>
* Follow best practices for servlets when implementing an IBM Content Navigator
* plug-in service. In particular, always assume multi-threaded use and do not
* keep unshared information in instance variables.
*/
public class MoveToRBService extends PluginService {
public static final String REPOSITORY_ID = "icnRepository";
public static final String REPOSITORY_TYPE = "serverType";
/**
* Returns the unique identifier for this service.
* <p>
* <strong>Important:</strong> This identifier is used in URLs so it must
* contain only alphanumeric characters.
* </p>
*
* @return A <code>String</code> that is used to identify the service.
*/
public String getId() {
return "MoveToRBService";
}
/**
* Returns the name of the IBM Content Navigator service that this service
* overrides. If this service does not override an IBM Content Navigator
* service, this method returns <code>null</code>.
*
* @returns The name of the service.
*/
public String getOverriddenService() {
return null;
}
/**
* Performs the action of this service.
*
* @param callbacks
* An instance of the <code>PluginServiceCallbacks</code> class
* that contains several functions that can be used by the
* service. These functions provide access to the plug-in
* configuration and content server APIs.
* @param request
* The <code>HttpServletRequest</code> object that provides the
* request. The service can access the invocation parameters from
* the request.
* @param response
* The <code>HttpServletResponse</code> object that is generated
* by the service. The service can get the output stream and
* write the response. The response must be in JSON format.
* @throws Exception
* For exceptions that occur when the service is running. If the
* logging level is high enough to log errors, information about
* the exception is logged by IBM Content Navigator.
*/
public void execute(PluginServiceCallbacks callbacks, HttpServletRequest request, HttpServletResponse response)
throws Exception {
String repositoryId = request.getParameter(REPOSITORY_ID);
String repositoryType = request.getParameter(REPOSITORY_TYPE);
JSONResponse jsonResponse = new JSONResponse();
ObjectStore objectStore = null;
JSONObject jsonObject = new JSONObject();
JSONObject finalJsonObj = new JSONObject();
JSONArray jsonArray = new JSONArray();
CmRecoveryBin bin = null;
try {
if (repositoryType.equals("p8")) {
Subject subject = callbacks.getP8Subject(repositoryId);
UserContext.get().pushSubject(subject);
System.out.println("in first if");
}
Object synchObject = callbacks.getSynchObject(repositoryId, repositoryType);
if (synchObject != null) {
synchronized (synchObject) {
if (repositoryType.equals("p8")) {
System.out.println(" synchObject Value :Ashok"+ synchObject.toString());
System.out.println("in synchronised block");
objectStore = callbacks.getP8ObjectStore(repositoryId);
System.out.println("ObjectStore!!!!!!!!!123" + objectStore.get_DisplayName());
}
}
SearchSQL sqlObject = new SearchSQL("select * from CmRecoveryBin");
SearchScope searchScope = new SearchScope(objectStore);
Integer myPageSize = new Integer(1000);
Boolean continuable = Boolean.valueOf(true);
IndependentObjectSet binSet = searchScope.fetchObjects(sqlObject, myPageSize, null, continuable);
// Iterate the set of recovery bins.
Iterator iterOuter = binSet.iterator();
while (iterOuter.hasNext()) {
bin = (CmRecoveryBin) iterOuter.next();
System.out.println("nRecovery bin: " + bin.get_DisplayName() + " ID: " + bin.get_Id());
jsonObject.put(bin.get_DisplayName(), bin.get_Id().toString());
jsonArray.add(jsonObject);
}
finalJsonObj.put("rb", jsonArray);
System.out.println("in cache control!!!!!!!!!!!!!!");
response.addHeader("Cache-Control", "no-cache");
response.setContentType("text/plain"); // must be text/plain for
// firebug
response.setCharacterEncoding("UTF-8");
Writer writer = response.getWriter();
writer.write(finalJsonObj.toString());
System.out.println("Printing results = " + finalJsonObj.toString());
}
} catch (Exception exc) {
JSONMessage message = new JSONMessage(0,
"The document could not be retrieved. Details have been written to the server error log.", null,
null, null, null);
jsonResponse.addErrorMessage(message);
exc.printStackTrace();
}
}
}
**BestDialog.html**
<div>
<select data-dojo-type="ecm/widget/ComboBox" data-dojo-attach-point="binlist"></select></div>