这会很长。
免责声明:这具体是我从前任继承的工作代码,所以我不知道为什么某些部分是这样编码的,只是它们确实如此。这是我没有完全理解其意图以及所使用的一些语法,因此这篇文章。如果可能的话,我宁愿不编辑导致问题的主文件之外的任何内容。 (我已经收到足够多的回复询问为什么我的代码是这样编写的,但没有回答这个让我有点烦恼的问题)
该程序的基本功能是从 SQL 表中读取数据并将其填充到屏幕上。然后,用户可以编辑几个字段并更新它;将其保存到数据库以供将来参考,或在数据库中创建新条目。
据我了解:-
表 A 和表 B 虽然总体不同,但都有一些相似的列,可以相互引用(未明确定义)
该程序通常运行良好,但是当我将表 B 中特定列的数据类型从 int 更改为 bigint 并访问现有数据的编辑屏幕时,我开始收到异常消息和函数中断(尽管整个程序仍然有效)。
错误消息仅出现在浏览器控制台日志中,指向cache.html中的一行。此错误在 2 个不同的浏览器(Chrome 和(IE 模式)Edge)中持续存在。
表 A 也有一个类似的列,声明为 int 并且存储过程通常在查询中引用它,所以我认为可能存在一些转换问题,但即使在将两个表中两列的数据类型都转换为 bigint 之后,错误仍然存在。
经过进一步检查,问题仅发生在表B中列的数据类型从int更改为bigint时。当我尝试将表 A 中的相关列从 int 更改为 bigint 进行匹配(不更改表 B 中列的数据类型)时,没有任何问题。
在 Java 之上,代码库还使用 GWT (2.4) 来填充屏幕,(编辑过的)相关代码包括:
客户端:
private StackTraceElement[] newResult;
protected void setNewStackTrace(StackTraceElement[] result){
Log.debug("Ex setNewStackTrace! " + result);
newResult = result;
}
protected void buildScreen() {
try {
GWT.setUncaughtExceptionHandler(new
GWT.UncaughtExceptionHandler() {
public void onUncaughtException(Throwable e) {
Log.debug("Ex caught!", e);
Log.debug("Ex getCause: ", e.getCause());
try { <Service>.Util.getInstance().getDeobfuscateStackTrace(e.getStackTrace(), new AsyncCallback<StackTraceElement[]>() {
public void onSuccess(StackTraceElement[] result) {
setNewStackTrace(result);
}
public void onFailure(Throwable caught) {
WidgetUtils.handleError(caught);
}
});
} catch (ApplicationException e1) {
// TODO Auto-generated catch block
Log.debug("Ex ApplicationException: ", e1);
e1.printStackTrace();
}
e.setStackTrace(newResult);
}
});
prepareGrid();
(...)
prepareMainButtons();
(...)
prepareFormBinding();
(...)
});
layout();
} catch (Exception e) {
AppsUtil.handleError(e);
}
}
(...)
private DbQuery QUERY = new DbQuery();
private PagingGridHelper<BaseModel> grid;
private String SELECTED_REPORT;
private Boolean LOADED = false;
private void prepareGrid() {
try {
QUERY.set_auditDbTable("<SQL Table>");
QUERY.setTableName("<Stored Procedure>");
List<ColumnConfig> columns = getColumns();
RpcProxy<PagingLoadResult<? extends ModelData>> proxy = new RpcProxy<PagingLoadResult<? extends ModelData>>() {
protected void load(Object loadConfig, AsyncCallback<PagingLoadResult<? extends ModelData>> callback) {
if (SELECTED_REPORT == null) {
if (LOADED)
callback.onSuccess(new BasePagingLoadResult<BaseModel>( new ArrayList<BaseModel>() ));
} else {
FilterPagingLoadConfig conf = (FilterPagingLoadConfig) loadConfig;
DbQueryService.Util.getInstance().selectPage(QUERY, conf, callback);
}
}
};
(...)
String columnData="";
for (int x=0; x<columns.size();x++){
columnData+=columns.get(x).getHeader() + ", ";
}
grid = new PagingGridHelper<BaseModel>(QUERY, columns, proxy, DOWNLOAD, false);
(...)
});
} catch (Exception e) {
AppsUtil.handleError(e);
}
}
private void prepareMainButtons() throws Exception {
(...)
EDIT = SWUtil.createButton(SWButton.EDIT);
EDIT.addSelectionListener(new SelectionListener<ButtonEvent>() {
public void componentSelected(ButtonEvent ce) {
(...)
if (grid.getSelectionModel().getSelection().size() == 1) {
(...)
switchMode(Mode.DataEdit, false);
// related to issue
formBinding.bind((BaseModel) grid.getSelectionModel().getSelection().get(0));
}
}
});
(...)
}
private void prepareFormBinding() {
try{
formBinding = new FormBinding(EditorForm, true);
formBinding.setStore(new ListStore<BaseModel>());
formBinding.addListener(Events.BeforeBind, new Listener<BindingEvent>() {
public void handleEvent(BindingEvent be) {
forceReset();
deselectAllCurrency();
EditorForm.reset();
(...)
}
});
formBinding.addListener(Events.Bind, new Listener<BindingEvent>() {
(...)
} catch (Exception e) {
e.printStackTrace();
}
}
});
formBinding.addListener(Events.UnBind, new Listener<BindingEvent>() {
(...)
}
catch(Exception e){
e.printStackTrace();
}
}
public PagingGridHelper(DbQuery dquery, List<ColumnConfig> uColumns, RpcProxy<PagingLoadResult<? extends ModelData>> uproxy, final BaseDownload download, boolean checkable) {
this.query = dquery;
this.columns = uColumns;
this.proxy = uproxy;
this.checkable = checkable;
try {
if (query == null)
query = new DbQuery();
(...)
columnModel = new ColumnModel(columns);
if (proxy == null) {
proxy = new RpcProxy<PagingLoadResult<? extends ModelData>>() {
protected void load(Object loadConfig, AsyncCallback<PagingLoadResult<? extends ModelData>> callback) {
FilterPagingLoadConfig conf = (FilterPagingLoadConfig) loadConfig;
DbQueryService.Util.getInstance().selectAsPage(query, conf, callback);
}
};
}
loadConfig = new BaseFilterPagingLoadConfig(0, pageSize);
loader = new BasePagingLoader<PagingLoadResult<D>>(proxy) {
protected Object newLoadConfig() {
return loadConfig;
}
};
loader.setRemoteSort(true);
loader.setReuseLoadConfig(true);
store = new ListStore<D>(loader);
store.addListener(Store.DataChanged, new Listener<StoreEvent<? extends ModelData>>() {
public void handleEvent(StoreEvent<? extends ModelData> be) {
for (ModelData d : store.getModels()) {
(...)
}
}
});
(...)
grid = new Grid<D>(store, columnModel);
(...)
grid.setLoadMask(true);
grid.setBorders(true);
(...)
grid.addListener(Events.Attach, new Listener<BaseEvent>() {
public void handleEvent(BaseEvent be) {
loader.load(0, pageSize);
}
});
} catch (Exception e) {
GWT.log(e.getMessage(), e);
}
}
服务器端:
@Override
public StackTraceElement[] getDeobfuscateStackTrace(StackTraceElement[] e) throws ApplicationException {
// TODO Auto-generated method stub
StackTraceDeobfuscator testDeobfuscator = new StackTraceDeobfuscator("war/WEB-INF/deploy/<project>/symbolMaps/");
String strongName = request.getHeader(RpcRequestBuilder.STRONG_NAME_HEADER);
return testDeobfuscator.deobfuscateStackTrace(e, strongName);
}
过了很长一段时间,我想我终于找到了问题的在哪里:
formBinding.bind((BaseModel) grid.getSelectionModel().getSelection().get(0));
好像和这个有关(准确的说,这部分没有命中)
formBinding.addListener(Events.Bind, new Listener<BindingEvent>() {
@SuppressWarnings("rawtypes")
public void handleEvent(BindingEvent be) {
(...)
} catch (Exception e) {
e.printStackTrace();
}
}
但我仍然不知道为什么,以及如何解决它。有什么想法吗?
如前所述,唯一改变的是表 B 中特定列的数据类型。此外,整个程序在 Chrome 和(IE 模式)Edge 中都按预期工作。
编辑2023年7月28日通读 GWT 文档,并尝试理解抛出的异常。
我得到这个是由于添加了上面的
GWT.setUncaughtExceptionHandler
:
编辑 4/8/2023 在 <style>PRETTY</style>
中实施
pom.xml
后更新异常图像。编辑 7/8/2023 在 <style>DETAILED</style>
中实施
pom.xml
后更新异常图像。
<servlet>
<servlet-name>remoteLogging</servlet-name>
<servlet-class>com.google.gwt.logging.server.RemoteLoggingServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>remoteLogging</servlet-name>
<url-pattern>/<project>/remote_logging</url-pattern>
</servlet-mapping>
selectAsPage
功能。
浏览其中的代码后,发现问题与实用程序函数之一有关,该函数处理从数据库查询读取的结果并将其转换为更标准化的 java 数据。public static <D extends BaseModel> void processRow(ResultSet rs, List<D> rows, D model) throws SQLException {
StringBuffer sb = new StringBuffer();
if (model == null)
model = (D) new BaseModel();
for (int i = 1 ; i <= rs.getMetaData().getColumnCount() ; i++) {
String column = rs.getMetaData().getColumnName(i);
if (rs.getMetaData().getColumnType(i) == Types.INTEGER) {
model.set(column, rs.getInt(i) );
}
else if (rs.getMetaData().getColumnType(i) == Types.BIGINT) {
model.set(column, rs.getBigDecimal(i).toBigInteger() );
}
else if(rs.getMetaData().getColumnType(i) == Types.NVARCHAR) {
model.set(column, rs.getString(i));
} else if (rs.getMetaData().getColumnType(i) == Types.TIMESTAMP) {
model.set(column, Misc.getTimestamp(rs, i) );
} else if (rs.getMetaData().getColumnType(i) == Types.FLOAT) {
model.set(column, new Double( rs.getFloat(i)) );
} else if (rs.getMetaData().getColumnType(i) == Types.DOUBLE) {
model.set(column, new Double( rs.getFloat(i)) );
} else if (rs.getMetaData().getColumnType(i) == Types.DECIMAL) {
Double d = new Double( rs.getDouble(i) );
model.set(column, d.doubleValue() );
} else if (rs.getMetaData().getColumnType(i) == Types.BIT) {
model.set(column, rs.getInt(i) );
} else {
model.set(column, rs.getString(i) );
}
sb.append(column + "=" + rs.getString(i) + "; type=" + rs.getMetaData().getColumnType(i));
}
rows.add( model );
具体来说,这个部分原本并不存在。
else if (rs.getMetaData().getColumnType(i) == Types.BIGINT) {
model.set(column, rs.getBigDecimal(i).toBigInteger() );
}
因此代码无法正确处理
BigInt
值;结果默认值为
String
,最终会导致前面提到的 ClassCastException
问题。一旦我添加了这个代码块(并修改了一些东西来适应它),问题或多或少就消失了。
这令人沮丧地花了我太长时间才确定。