public void init() {
		// Start GUI
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				JFrame frame = new JFrame("Auction System Server");
				JPanel content = new JPanel();
				final JButton generateReport = new JButton("Generate Report");
				final JButton start = new JButton("Start Server");
				start.setEnabled(false);
				final JButton stop = new JButton("Stop Server");
				final JTextArea report = new JTextArea();
				JScrollPane reportScroll = new JScrollPane(
											report,
											JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
											JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
				report.setEditable(false);
				
				generateReport.addActionListener(new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent arg0) {
						report.setText("Ended auctions:\n");
						try {
							storage.selectDb("items");
							Set<Object> keys = storage.keySet();
							String format = "%s\nItem #%d - '%s':\nWon by %s %s for %s on %s\n";
							Item item;
							String bidderId;
							User bidderProfile;
							for (Object key : keys) {
								item = (Item) storage.readObject(key);
								if (item.getHighestBid() != null) {
									if (item.timeLeft() == 0) {
										bidderId = item.getHighestBid().username;
										storage.selectDb("users");
										bidderProfile = (User) storage.readObject(bidderId);
										
										if (bidderProfile == null) {
											bidderProfile = new User();
											bidderProfile.setFirstName("anonymous");
											bidderProfile.setLastName("user");
										}
										report.setText(
												String.format(
														format,
														report.getText(), 
														key,
														item.getTitle(),
														bidderProfile.getFirstName(),
														bidderProfile.getLastName(),
														item.getHighestBid().formatted(),
														item.getEnd().toString()));
									}
								}
								storage.selectDb("items");
							}
						} catch (IOException ex) {
							Alerter.getHandler().severe("Persistence Error",
									"Unable to retrieve item information.");
						}
					}
				});
				
				start.addActionListener(new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent arg0) {
						start.setEnabled(false);
						setup();
						stop.setEnabled(true);
					}
				});
				
				stop.addActionListener(new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent arg0) {
						stop.setEnabled(false);
						close();
						start.setEnabled(true);
					}
				});
				
				// Layout code
				GroupLayout contentLayout = new GroupLayout(content);
				contentLayout.setHorizontalGroup(contentLayout.createSequentialGroup()
					.addContainerGap()
					.addGroup(contentLayout.createParallelGroup()
						.addComponent(reportScroll)
						.addComponent(generateReport, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)
						.addGroup(contentLayout.createSequentialGroup()
							.addComponent(start, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)
							.addPreferredGap(ComponentPlacement.UNRELATED)
							.addComponent(stop, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)
						)
					)
					.addContainerGap()
				);
				contentLayout.setVerticalGroup(contentLayout.createSequentialGroup()
					.addContainerGap()
					.addComponent(reportScroll)
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addComponent(generateReport)
					.addPreferredGap(ComponentPlacement.RELATED)
					.addGroup(contentLayout.createParallelGroup()
						.addComponent(start)
						.addComponent(stop)
					)
					.addContainerGap()
				);
				content.setLayout(contentLayout);
				
				frame.setContentPane(content);
				frame.pack();
				frame.setSize(new Dimension(480, 500));
				frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
				frame.setVisible(true);
			}
		});
		
		setup();
	}