Java no response from other classes - java

I have this GUI program where I'm trying to basically copy windows CMD. Since I have lots of features in this program, I decided to put parts of the code in different classes. But it doesn't respond.
if(command.size()<2 && command.size()>0) {
switch(command.get(0)) {
case "dt":
getDateTime a = new getDateTime();
a.Start();
break;
// other case(s) down below
}
}
Here is the geDateTime class
public class getDateTime {
public static void Start() {
Terminal t = new Terminal();
try {
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Date date = new Date();
String s = dateFormat.format(date).toString();
t.print(s);
}catch(Exception e){ e.printStackTrace(); }
}
}
Here is the print(); void in the main class...
public static void print(String s) {
Color c = Color.WHITE; // prints white text to JFrame
Style style = output.addStyle("Style", null);
StyleConstants.setForeground(style, c);
try{
document.insertString(document.getLength(), s, style);
}catch(Exception e){e.printStackTrace();}
}
Now when I enter the command for accessing the getDateTime class, the program freezes and I can't input anything. HOWEVER, if I just put the getDateTime class into a void inside the main class it works fine; but this would be a problem to just put everything into the main class since some function(s) could have hundreds of line of code.
No errors are produced when the program freezes.

In the code snippet that you have earlier, the code was trying to create a new Terminal rather than using the existing one.
Try this:
private static void print() {
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Date date = new Date();
String s = dateFormat.format(date).toString();
print(s);
}
In the access method:
case "dt":
print();
break;
Update: On a side note, try to avoid static if at all possible. Generally speaking, it's bad practice. See https://stackoverflow.com/a/7026563/1216965

Related

Java: Logging: Custom Formatter

I wrote a simple Custom Formatter for my logging that prints a DateTime in the specified format. Everything works fine, but the datetime doesn't get printed in my log file. Below is my CustomFormatter.java:
CustomFormatter.java:
public class CustomFormatter extends Formatter {
SimpleDateFormat sdf;
public CustomFormatter() {
sdf = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
}
public String format(LogRecord rec) {
StringBuffer buf = new StringBuffer(1000);
buf.append(formatMessage(rec));
return buf.toString();
}
public String getHead(Handler h) {
return (sdf.format(new java.util.Date()) + ": \t");
}
public String getTail(Handler h) {
return "\n";
}
}
Im my main class, I initialize my logger as:
Main.java:
private static Logger logger = Logger.getLogger("org.somecompany.someproject");
public static void main(String[] args){
try{
String _pattern = "myLogger.log.%g";
int numLogFiles = 10;
int fileSize = 1000000;
boolean appendToFile = true;
FileHandler fh = new FileHandler(pattern, fileSize, numLogFiles, appendToFile);
fh.setFormatter(new CustomFormatter());
logger.addHandler(fh);
logger.setLevel(Level.ALL);
} catch(IOException i) { System.out.println("Unable to init logger");}
logger.info("Begin");
logger.info("Line 1");
logger.info("Line 2");
logger.info("End");
fh.close();
fh = null;
}
The log file should have a datetime printed at the beginning of each line and it isn't. Any help is appreciated.
I think you misunderstand the purpose of getHead() and getTail().
Those methods are not called per log entry - getHead() is called once before the Handler (FileHandler) logs the first entry and getTail() is called once before the Handler (FileHandler) closes the log stream.
This is used for example in the XMLFormatter to create a valid XML file (where there must be an XML start tag before the first log entry and an XML end tag after the last log entry to be valid XML).
If you look closely at the created log file this is exactly what happens: the log file creates a timestamp at the start and ends with a newline.
Note that adding time stamps to your log entries doesn't require writing a CustomFormatter. Properly configuring a SimpleFormatter is enough for your purpose.

After set the location, timezone can't convert

Below is my coding:
private final String TIME_ZONE_ID_TRKD_DEFAULT = "Etc/GMT";
private XMLGregorianCalendar getStartDateTime(boolean startFromZeroHour) {
XMLGregorianCalendar xmlCal = null;
try {
xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar();
} catch (DatatypeConfigurationException e) {
e.printStackTrace();
}
Calendar now = Calendar.getInstance(TimeZone.getTimeZone("Asia/Singapore"));
now.setTimeZone(TimeZone.getTimeZone(TIME_ZONE_ID_TRKD_DEFAULT));
xmlCal.setDay(now.get(Calendar.DAY_OF_MONTH));
xmlCal.setMonth(now.get(Calendar.MONTH) + 1);
xmlCal.setYear(now.get(Calendar.YEAR));
xmlCal.setTime(now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), now.get(Calendar.SECOND));
please kindly advice why it can't convert, and how should i do..
The code cannot be compiled because of an error on the line, where you get the instance of the calendar. I believe you wanted to do this (probably just copy/paste error?):
Calendar now = Calendar.getInstance(TimeZone.getTimeZone("Asia/Singapore"));
A better approach might be the following:
private final String TIME_ZONE_ID_TRKD_DEFAULT = "Etc/GMT";
private XMLGregorianCalendar getStartDateTime(boolean startFromZeroHour) {
XMLGregorianCalendar xmlCal = null;
try {
xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar(TimeZone.getTimeZone(TIME_ZONE_ID_TRKD_DEFAULT)));
} catch (DatatypeConfigurationException e) {
e.printStackTrace();
}
xmlCal.setMillisecond(DatatypeConstants.FIELD_UNDEFINED);
xmlCal.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
if(startFromZeroHour){
xmlCal.setHour(0);
}
return xmlCal;
}
public static void main(String[] args) {
Bug b = new Bug();
XMLGregorianCalendar startDateTime = b.getStartDateTime(true);
System.out.println(startDateTime);
XMLGregorianCalendar startDateTime2 = b.getStartDateTime(false);
System.out.println(startDateTime2);
}
First we create a GregorianCalendar instance using your timezone constant. It represents the current time (now) if the default constructor is used.
Then we use it to initialize the XMLGregorianCalendar.
You don't want to have the milliseconds and the timezone part, so we just unset them using DatatypeConstants.FIELD_UNDEFINED as stated in the JavaDoc https://docs.oracle.com/javase/7/docs/api/javax/xml/datatype/XMLGregorianCalendar.html#setMillisecond(int) .
I added a part setting the hour to zero if startFromZeroHour is set to true. It was not part of your code so you might want to remove or change it.

How to write a junit test script?

I wrote a java code which is working but I have to write a Junit Test Script for it, but I do not have the experience yet. I tried several hours, but I can not understand how it works. So your help is very welcomed. Thanks in advance :) Do you have any tipps for me? :)
import java.awt.*;
import java.awt.event.*;
class MailBox extends Frame {
private boolean request;
private String message;
TextField tf1;
public MailBox() {
Dimension screenDim = getToolkit().getScreenSize();
Dimension frameDim = getPreferredSize();
setLocation((screenDim.width-frameDim.width)/2, (screenDim.heightframeDim.height)/2); addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
}
Panel myPanel = new Panel();
myPanel.setLayout(new FlowLayout());
Label label1 = new Label("Message: ");
Button button1 = new Button("Send");
button1.addActionListener(new button1AL());
tf1 = new TextField("", 20);
myPanel.add(label1);
myPanel.add(tf1);
myPanel.add(button1);
add(myPanel, BorderLayout.CENTER);
setTitle("Mailbox");
pack();
show();
}
public synchronized void storeMessage(String message){
while(request==true){
try{
wait();
}
catch(InterruptedException e){
}
}
request = true;
this.message = message;
notify();
}
public synchronized String retrieveMessage(){
while(request==false){
try{
wait();
}
catch(InterruptedException e){
}
}
request=false;
notify();
return message;
}
public static void main(String args[]) {
System.out.println("Starting Mailbox...");
MailBox MyMailBox = new MailBox();
Consumer c1 = new Consumer(MyMailBox);
Thread t1 = new Thread(c1);
t1.start();
}
class button1AL implements ActionListener{
public void actionPerformed(ActionEvent ae){
storeMessage(tf1.getText());
tf1.setText("");
}
}
}
I would say that in your case the program did not reach yet the level when it should be Unit tested. I don't see any reason why you need to test that some constructor works when it just initializes the fields of the class and also that the program prints something. I would not check that.
In the case when you get some error and this error might contain different error messages, it is a good idea to verify that the message is the same, but this is not your case. So, the main point is that your unit test should test business logic.
Consider this template:
#Test
public void testGoUntilTankIsEmpty() throws Exception {
// SETUP SUT
Car car = new Car();
car.fillFullTank();
car.setSpeed(80);
// EXERCISE
int distanceInKm = car.goUntilTankIsEmpty();
// VERIFY
Assert.assertEquals(800, distanceInKm);
}
In this case we exercise (test) specified method and expect that the result will be 800 based on our preliminary setup. If it is true your unit test will pass otherwise it will fail.
And remember that unit test should test only some unit, so some small piece of code, but actual functionality.
JUnit's work by testing the code you have written with either the expected output, or incorrect output if you want to test whether your error handling works.
In your case you'd just test against the expected string it outputs.
So a basic test for what you have would look something along the lines of...
import org.junit.Test;
import org.junit.Assert.assertEquals
public class BasicTest{
#Test
public void describeAnimalTest(){
AnimalNew animal = new AnimalNew("Dog", 10, "x");
assertEquals("Dog is on level 10 und is a type of x", animal.describeAnimal();
}
}

JUnit test a static void method [duplicate]

This question already has answers here:
How to test void method with Junit testing tools?
(6 answers)
Closed 9 years ago.
So I created a log function so I can see the date of every action. I now want to unittest them. Because the function uses a void, I can't test the output.
I might change the void to a String, but then the point of using it as a void would be gone!
What are my options?
public class Logger {
public static void log(String s) {
Date d = new Date();
SimpleDateFormat ft =
new SimpleDateFormat ("yyyy.MM.dd '-' hh:mm:ss");
System.out.println("[" + ft.format(d) + "]: " + s);
}
}
JUnit
#Test
public void testLoggerEmptyString() {
String s = "";
log(s);
}
Thanks :D
You need to test the side effects of your method. In this case, the side effect you want to observe is something getting written to System.out. You can use System.setOut to install your own OutputStream. From there you can verify that something was written to it.
For instance:
String s = "your message";
ByteArrayOutputStream sink = new ByteArrayOutputStream();
System.setOut(new PrintStream(sink, true));
log(s);
assertThat(new String(sink.toByteArray()), containsString(s));
You can use the library System Rules. It automatically sets the System.out back after the test.
public void MyTest {
#Rule
public final StandardOutputStreamLog log = new StandardOutputStreamLog();
#Test
public void testLoggerEmptyString() {
log("hello world");
assertEquals("hello world", log.getLog());
}
}
I might change the void to a String, but then the point of using it as a void would be gone!
I don't think so. If your method would look like this:
public static String getLogMessage(String s) {
Date d = new Date();
SimpleDateFormat ft = new SimpleDateFormat ("yyyy.MM.dd '-' hh:mm:ss");
return String.format("[%s] %s", ft.format(d), s);
}
You could test the output and use it in your code with
System.out.println(Whatever.getLogMessage("Foo for the world"));
or even
System.err.println(Whatever.getLogMessage("Holy shit!"));

Access an object from another class

I have a few classes and one main method. The program is used to connect to an Access database and retrieve information.
I have a class which deals with the GUI only (to display the results) in one JTextArea box. Another class runs a while loop and pulls in data from the database and assigns it to a String as such:
line = (line+upid+"\t"+StreetNum+"\t"+suburb+"\t"+area+"\t"+price+"\t"+agentID+"\t"+numBeds+"\t"+numBaths+"\t"+spool+"\t"+numGarages+"\t"+date+"\t"+ownerID+"\t"+SaleOrRent+"\n");
Basically my question is how do I access the String line from the GUI Class so that I can use txtArea.setTextto display line bearing in mind the GUI has no Main Method?
EDIT:
To try get around this, I have created a LineObject which takes line in as a parameter. I then call the getLine from the void addComponents but it gives a nullPointerException?
Here is the searchProps class:
import java.awt.Container;
import java.sql.*;
import java.util.*;
import javax.swing.*;
public class searchProps
{
protected String price, area, query, suburb, date, SaleOrRent, strQuery, out, line="";
protected int agentID, upid, StreetNum, numBeds, numBaths, numGarages, ownerID, size;
protected boolean spool;
PropertyObject PropertyArray[] = new PropertyObject[3];
LineObject obj;
JFrame jf;
JTextArea txtArea = new JTextArea();
{
initialFrame();
addComponents();
}
public searchProps(int propID) //search using UPID only
{
try
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection conn = DriverManager.getConnection("jdbc:odbc:PropertyOracleDatabase");
Statement s = conn.createStatement();
query = ("SELECT * FROM Properties WHERE UPID = "+propID);
// Fetch table
s.execute(query);
ResultSet rs = s.getResultSet();
while((rs!=null) && (rs.next()))
{
upid=rs.getInt(1);
StreetNum=rs.getInt(2);
suburb=rs.getString(3);
area=rs.getString(4);
price=rs.getString(5);
agentID= rs.getInt(6);
numBeds=rs.getInt(7);
numBaths=rs.getInt(8);
spool=rs.getBoolean(9);
numGarages=rs.getInt(10);
date=rs.getString(11);
ownerID=rs.getInt(12);
SaleOrRent=rs.getString(13);
size++;
line = (line+upid+"\t"+StreetNum+"\t"+suburb+"\t"+area+"\t"+price+"\t"+agentID+"\t"+numBeds+"\t"+numBaths+"\t"+spool+"\t"+numGarages+"\t"+date+"\t"+ownerID+"\t"+SaleOrRent+"\n");
obj= new LineObject(line);
System.out.println(line);
String out = obj.getLine();
System.out.println(out);
}
// close and cleanup
s.close();
conn.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
void initialFrame()
{
jf=new JFrame();
jf.setSize (1300,700);
jf.setTitle("Property Oracle | Results Page");
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
void addComponents()
{
Container con = jf.getContentPane();
con.setLayout(null);
txtArea.setBounds(20,30,1200,600);
con.add(txtArea);
txtArea.setText("UPID\tStreetNum\tSuburb\tArea\tPrice\tAgentID\tBedrooms\tBathrooms\tSwimming Pool\tGarages\tDate\tOwner\tSale/Rent\n");
out = obj.getLine();
System.out.println(out);
}
}
And here is the LineObject class:
public class LineObject
{
protected String line;
public LineObject(String a)
{
line = a;
}
public String getLine()
{
return line;
}
}
I will assume your database access code runs in a separate thread, otherwise typical latency would block the event dispatch thread (EDT). Pass a reference to your JTextArea as a parameter to your database code. Use the reference to update the JTextArea on the EDT:
final String line = …
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ta.append(line);
}
});
A related example is seen here.
Make line a private class field of your class (the one that runs the while loop).
public LoopingClass {
private String line;
public void loopMethod() {
line = //...
}
}
Then create a public getter to this variable.
public LoopingClass {
private String line;
public void loopMethod() {
line = //...
}
public String getLine() {
return line;
}
}
Then from your GUI, call the getter of the object instance.
// somewhere in your GUI class
loopingClassInstance.getLine();
Take a look at the MVC pattern: it's always good practice to decouple the business logic (putting data in a database and building the string "line") from the frontend (GUI).
By the way, since you're building the string by appending more data to it, you should consider using a StringBuilder instead:
StringBuilder lineBuilder = new StringBuilder();
// append data:
lineBuilder.append(someString);
// create a string only when you need it:
String line = lineBuilder.toString();
In this way you are not continuosly creating new strings (which can be expensive in the long run especially if the string keeps growing), but using the buffer provided by the StringBuilder and then creating an actual string only when you need it, e.g., when you need to update your JTextArea.

Categories

Resources