我已经编写了第一个Java小程序,并在将其部署到Web服务器上时出错.我的applet使用了几个其他的jar文件,例如javaMail mail.jar,smtp.jar,mailapi.jar和其他文件.当我尝试在Web浏览器中显示我的applet时,我在“错误对话框”中得到了这样的信息:
java.lang.RuntimeException: java.lang.NoClassDefFoundError: javax/mail/Authenticator
..
Caused by: java.lang.NoClassDefFoundError: javax/mail/Authenticator
... 20 more
我对Web应用程序不是很好,并且不确定是什么导致此错误.根据信息,我认为我的小程序无法加载库.那么我该如何解决呢?我的服务器在/ lib目录中有这些库.所有其他文件都在主目录中.我的HTML文件如下:
<HTML>
<HEAD>
<TITLE>TPSA Speed Test</TITLE>
</HEAD>
<BODY>
<P>
<APPLET code="speedtester_pkg/AppletMain.class" archive="SpeedTester.jar" width=440 height=600></APPLET>
</P>
</BODY>
</HTML>
我也尝试使用JNLP将小程序加载到Web浏览器,效果相同.我试图找到某种方法来指向HTML文件中的那些库,但是却没有进行管理(试图在JNLP文件中添加另一个jar归档行或nativelib).我也尝试使用我的applet类将这些库添加到jar文件中,但这也无济于事.
这是我在其中使用javaMail的代码(代码结尾附近的sendTestResults()方法):
/*
* AppletMain.java
*/
package speedtester_pkg;
import java.awt.*;
import java.beans.*;
import java.io.*;
import java.util.*;
import java.util.logging.*;
import javax.swing.*;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class AppletMain extends javax.swing.JApplet implements PropertyChangeListener{
private ArrayList<String> customerFields;
private DataReader dataReader;
private Test test;
private FileHandler fh;
private ProgressBarTask progressBarTask;
private JTextField[] customerData;
private String speed, cpuLoad, NICspeed, testTime;
private int timeDef = 60;
/**
* The input file directory
*/
// public String directory = "C:\\Documents and Settings\\Administrator\\Pulpit\\";
public String filename = "speedtestData.txt";
/**
* Input file should be a simple "*.txt" file named "speedtestData.txt"
*/
public File file;
// mail sending data
/**
* TO DO encrypt mailing data
*/
private String smtpHost = "smtp.gmail.com",
username = "myUserName",
password = "myPassword";
private int port = 465; // TLS 587/ SSL 465
/** Initializes the applet Applet */
@Override
public void init() {
try {
java.awt.EventQueue.invokeAndWait(new Runnable() {
public void run() {
createGUI();
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
}
/** This method is called from within the init() method to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
infoPanel = new javax.swing.JPanel();
labelLogo = new javax.swing.JLabel();
labelTitle = new javax.swing.JLabel();
labelLinkSpeed = new javax.swing.JLabel();
labelProcessorLoad = new javax.swing.JLabel();
labelNIC = new javax.swing.JLabel();
buttonStart = new javax.swing.JButton();
jLabel4 = new javax.swing.JLabel();
jLabel5 = new javax.swing.JLabel();
jLabel6 = new javax.swing.JLabel();
jProgressBar = new javax.swing.JProgressBar();
formPanel = new javax.swing.JPanel();
jLabel8 = new javax.swing.JLabel();
buttonSend = new javax.swing.JButton();
labelForm = new javax.swing.JLabel();
infoLabel = new javax.swing.JLabel();
jScrollPane = new javax.swing.JScrollPane();
commentText = new javax.swing.JTextArea();
labelTitle.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N
labelTitle.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
labelTitle.setText("Link Speed Test");
labelLinkSpeed.setFont(new java.awt.Font("Tahoma", 1, 24)); // NOI18N
labelLinkSpeed.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
labelProcessorLoad.setFont(new java.awt.Font("Tahoma", 1, 18)); // NOI18N
labelProcessorLoad.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
labelNIC.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
labelNIC.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
buttonStart.setText("Start");
buttonStart.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonStartActionPerformed(evt);
}
});
jLabel4.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
jLabel4.setText("Szybkość łącza:");
jLabel5.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
jLabel5.setText("Obciążenie procesora:");
jLabel6.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
jLabel6.setText("Szybkość karty sieciowej:");
javax.swing.GroupLayout infoPanelLayout = new javax.swing.GroupLayout(infoPanel);
infoPanel.setLayout(infoPanelLayout);
infoPanelLayout.setHorizontalGroup(
infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, infoPanelLayout.createSequentialGroup()
.addComponent(labelLogo, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(infoPanelLayout.createSequentialGroup()
.addGroup(infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel5)
.addComponent(jLabel6)
.addComponent(jLabel4))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(labelLinkSpeed, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 146, Short.MAX_VALUE)
.addComponent(labelProcessorLoad, javax.swing.GroupLayout.DEFAULT_SIZE, 146, Short.MAX_VALUE)
.addComponent(labelNIC, javax.swing.GroupLayout.DEFAULT_SIZE, 146, Short.MAX_VALUE)))
.addComponent(labelTitle, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 289, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(22, 22, 22))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, infoPanelLayout.createSequentialGroup()
.addContainerGap(352, Short.MAX_VALUE)
.addComponent(buttonStart, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE))
);
infoPanelLayout.setVerticalGroup(
infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(infoPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, infoPanelLayout.createSequentialGroup()
.addComponent(labelTitle)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 31, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(labelLinkSpeed, javax.swing.GroupLayout.DEFAULT_SIZE, 31, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel5)
.addComponent(labelProcessorLoad, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(infoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel6)
.addComponent(labelNIC, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(6, 6, 6))
.addGroup(infoPanelLayout.createSequentialGroup()
.addGap(16, 16, 16)
.addComponent(labelLogo, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 8, Short.MAX_VALUE)
.addComponent(buttonStart)
.addContainerGap())
);
javax.swing.GroupLayout formPanelLayout = new javax.swing.GroupLayout(formPanel);
formPanel.setLayout(formPanelLayout);
formPanelLayout.setHorizontalGroup(
formPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 417, Short.MAX_VALUE)
);
formPanelLayout.setVerticalGroup(
formPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 127, Short.MAX_VALUE)
);
jLabel8.setText("Uwagi:");
buttonSend.setText("Wyślij");
buttonSend.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonSendActionPerformed(evt);
}
});
labelForm.setFont(new java.awt.Font("Tahoma", 0, 14));
labelForm.setText("Formularz:");
infoLabel.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
infoLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
infoLabel.setText("Kliknij przycisk \"Start\" aby rozpocząć test");
commentText.setColumns(20);
commentText.setRows(5);
jScrollPane.setViewportView(commentText);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 437, Short.MAX_VALUE)
.addGap(0, 437, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 417, Short.MAX_VALUE)
.addComponent(formPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(infoLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 417, Short.MAX_VALUE)
.addComponent(jLabel8, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, 417, Short.MAX_VALUE)
.addComponent(infoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(labelForm)
.addComponent(buttonSend, javax.swing.GroupLayout.Alignment.TRAILING))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 572, Short.MAX_VALUE)
.addGap(0, 572, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(infoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(infoLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 29, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(labelForm)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(formPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel8, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(buttonSend)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// </editor-fold>
public void createGUI()
{
try {
dataReader = new DataReader(this);
dataReader.read();
customerFields = dataReader.getCustomerFields();
testTime = String.valueOf(dataReader.getTestTime());
initComponents();
generateCustomerForm();
test = new Test(this, dataReader.getDownloadURLs(), dataReader.getTestTime());
} catch (ClassNotFoundException ex) {
Logger.getLogger(AppletMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
Logger.getLogger(AppletMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(AppletMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (UnsupportedLookAndFeelException ex) {
Logger.getLogger(AppletMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (FileNotFoundException ex) {
Logger.getLogger(AppletMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void buttonStartActionPerformed(java.awt.event.ActionEvent evt) {
buttonStart.setEnabled(false);
infoLabel.setText("Poczekaj do końca testu...");
progressBarTask = new ProgressBarTask(this);
infoLabel.setText("progress bar");
progressBarTask.addPropertyChangeListener(this);
progressBarTask.execute();
Thread testThread = new Thread(this.test);
testThread.start();
System.out.println("Test thread \"" + testThread.getName() + "\" started.");
}
private void buttonSendActionPerformed(java.awt.event.ActionEvent evt) {
try {
sendTestResults();
} catch (MessagingException ex) {
Logger.getLogger(AppletMain.class.getName()).log(Level.SEVERE, null, ex);
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(AppletMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void generateCustomerForm() throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException
{
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
//correcting auto-generated layout
jLabel8.setFont(new java.awt.Font("Tahoma", 0, 11));
labelProcessorLoad.setAlignmentX(RIGHT_ALIGNMENT);
labelLogo.setIcon(new ImageIcon(getImage(getDocumentBase(), "orange.jpeg")));
//gereate JLabels and JTextFields read from file
GridBagLayout gridBagLayout = new GridBagLayout();
GridBagConstraints gbc = new GridBagConstraints();
formPanel.setLayout(gridBagLayout);
customerData = new JTextField[customerFields.size()];
for(int i=0; i<customerFields.size(); i++)
{
JLabel l = new JLabel(customerFields.get(i));
l.setFont(new java.awt.Font("Tahoma", 0, 11));
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx=0;
gbc.gridy=i;
gbc.weightx = 0.5;
gbc.weighty = 0.5;
formPanel.add(l, gbc);
JTextField t = new JTextField();
t.setFont(new java.awt.Font("Tahoma", 0, 11));
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx=1;
gbc.gridy=i;
gbc.weightx = 0.5;
gbc.weighty = 0.5;
formPanel.add(t, gbc);
customerData[i] = t;
}
}
/**
* Invoked when task's progress property changes.
*/
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("progress")) {
int progress = (Integer) evt.getNewValue();
jProgressBar.setValue(progress);
}
}
public void setLabelProcessorLoad(String text)
{
labelProcessorLoad.setText(text);
}
public void setLabelLinkSpeed(String text)
{
labelLinkSpeed.setText(text);
}
public void setLabelNIC(String text)
{
labelNIC.setText(text);
}
public JProgressBar getProgressBar()
{
return jProgressBar;
}
public JButton getButtonStart()
{
return buttonStart;
}
public Test getTest()
{
return this.test;
}
public void setNICspeed(String NICspeed) {
this.NICspeed = NICspeed;
}
public void setCpuLoad(String cpuLoad) {
this.cpuLoad = cpuLoad;
}
public void setSpeed(String speed) {
this.speed = speed;
}
public JLabel getInfoLabel() {
return infoLabel;
}
/**
* Prepares e-mail message for sending via google SMTP protocol with SSL
*/
private void sendTestResults() throws MessagingException, UnsupportedEncodingException{
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class",
"javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");
Session session = Session.getDefaultInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username,password);
}
});
MimeMessage message = new MimeMessage(session);
//Setting message fields
Address toAddress = new InternetAddress(dataReader.getMail(), "SpeedTest crew");
message.addRecipient(Message.RecipientType.TO, toAddress);
message.setSubject("SpeedTest");
message.setText(prepareMailText(), "UTF8");
Transport.send(message);
infoLabel.setText("Wiadomość z wynikami testu została wysłana pomyślnie");
System.out.println("Mail sent.");
}
/**
* Gets all test results and customer data and prepares mail content
* @return the content of e-mail body
*/
private String prepareMailText()
{
String messageContentHeader = "Prędkość pobierania\t" + "Obciążenie procesora\t" +
"Szybkość łącza karty sieciowej\t" + "Czas trwania testu\t";
String messageContent = speed + "\t"+ cpuLoad + "\t" + NICspeed + "\t" + testTime + "\t";
for(int j=0;j<customerData.length;j++)
{
messageContentHeader += customerFields.get(j) + "\t";
messageContent += customerData[j].getText() + "\t";
}
messageContentHeader += "Uwagi";
messageContent += commentText.getText();
String messageText = messageContentHeader + "\n" + messageContent;
return messageText;
}
// Variables declaration - do not modify
private javax.swing.JButton buttonSend;
private javax.swing.JButton buttonStart;
private javax.swing.JTextArea commentText;
private javax.swing.JPanel formPanel;
private javax.swing.JLabel infoLabel;
private javax.swing.JPanel infoPanel;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabel8;
private javax.swing.JProgressBar jProgressBar;
private javax.swing.JScrollPane jScrollPane;
private javax.swing.JLabel labelForm;
private javax.swing.JLabel labelLinkSpeed;
private javax.swing.JLabel labelLogo;
private javax.swing.JLabel labelNIC;
private javax.swing.JLabel labelProcessorLoad;
private javax.swing.JLabel labelTitle;
// End of variables declaration
}
我对Sigar.jar之类的其他库也遇到了问题,但我想它将解决类似问题.
有人有好的秘诀?
解决方法:
必须将包含javax.mail包的Jar添加到applet的运行时类路径中.要实现这一目标(一种方法是),将Jar放在相同的地方SpeedTester.jar并从以下位置更改archive属性:
archive="SpeedTester.jar"
..至:
archive="SpeedTester.jar,mail.jar"
更新1
更改整个applet元素:
从
<APPLET
code="speedtester_pkg/AppletMain.class"
archive="SpeedTester.jar"
width=440
height=600>
</APPLET>
至
<APPLET
code="speedtester_pkg.AppletMain"
archive="SpeedTester.jar,mail.jar"
width=440
height=600>
</APPLET>
假定applet类的包是speedtester_pkg,并且applet名为AppletMain. code属性应该是applet类的完全限定名称,而不是路径/文件名.
更新2
以上建议重新. mail.jar不考虑从Test,DataReader或ProgressBarTask内部引用的类(或它们加载的类). “冲洗并重复”该建议,以便使用archive属性将额外的API添加到运行时类路径.
注意
似乎其他答案都指向网络应用程序.那完全是服务器端的.对于这样的网络应用程序,将Jars放入lib是有意义的.小程序只能通过将Jar的URL复制/粘贴到浏览器地址栏中并按Enter来访问可用的Jar.
实际上,通过结合使用代码库和Jar的href是对applet是否能够访问档案的良好“酸性测试”.