Search code examples
javasqljavafxwebviewderby

Trying to create javafx app that allows the user to easily monitor and maintain a list of websites in embedded derby database


I want to allow the user to drag and drop a link onto the list, which will enter the URL into the database, allow the user to view all links, articles, or something similar on the page in the upper right corner(even simple details such as title and when link was added would be fine), and then view the webview. I cant get it to correctly display the URL details in the upper right corner, or display the webview correctly in the bottom right. I am very familiar with javafx and derby, just not so much with the web aspect. Any help would be greatly appreciated. As of now, the URL can be dragged and dropped onto the list, and the title and some details are displayed incorrectly in the upper right. The webview doesn't work either most of the time. The hyperlink doesn't get displayed correctly in the list either, but that is just some formatting that needs fixed. The end goal is just to allow the user to monitor new posts, articles, or news, on the URLs they enter.

DBUtils.java

public class DBUtils {
    final static Properties props = new Properties(); 
    static {
        props.put("user", "admin");
        props.put("password", "letmein");
    }
    private static String framework = "embedded";
    private static String driver = "org.apache.derby.jdbc.EmbeddedDriver";
    private static String protocol = "jdbc:derby:";
    public static void setupDb() {
        loadDriver();
        Connection conn = null;
        ArrayList statements = new ArrayList(); 
        Statement s = null;
        ResultSet rs = null;
        try {
            String dbName = "UrlDB"; 
            conn = DriverManager.getConnection(protocol + dbName + ";create=true", props);
            System.out.println("Creating database " + dbName);
            boolean createTable = false;
            s = conn.createStatement();
            try {
                s.executeQuery("SELECT count(*) FROM urlFeed");
            } catch (Exception e) {
                createTable = true;
            }     
            if (createTable) {
                conn.setAutoCommit(false);
                s = conn.createStatement();
                statements.add(s);
                s.execute("CREATE TABLE UrlFeed(ID INT, Title VARCHAR(255), Url VARCHAR(600))");
                System.out.println("Created table UrlFeed ");
                conn.commit();
            }         
            shutdown();
        } catch (SQLException sqle) {
            sqle.printStackTrace();
        } finally {         
            close(rs);
            int i = 0;
            while (!statements.isEmpty()) {
                Statement st = (Statement) statements.remove(i);
                close(st);
            }
            close(conn);
        }} 
    public static List<UrlFeed> loadFeeds() {
        loadDriver();
        Connection conn = null;
        ResultSet rs = null;
        List<UrlFeed> feeds = new ArrayList<>();
        try {
            String dbName = "UrlDB"; 
            conn = DriverManager.getConnection(protocol + dbName + ";create=true", props);
            rs = conn.createStatement().executeQuery("SELECT ID, Title, Url FROM UrlFeed");
            while (rs.next()) {
                String title = rs.getString("title");
                String url = rs.getString("url");
                UrlFeed urlFeed = new UrlFeed(title, url);
                urlFeed.id = urlFeed.link.hashCode();
                feeds.add(urlFeed);
            } 
            shutdown();
        } catch (SQLException sqle) {
            sqle.printStackTrace();
        } finally {         
            close(rs);
            close(conn);
        }
        return feeds;
    }
    private static void shutdown() {
        if (framework.equals("embedded")) {
            try {
                DriverManager.getConnection("jdbc:derby:;shutdown=true");
            } catch (SQLException se) {
                if (((se.getErrorCode() == 50000)
                        && ("XJ015".equals(se.getSQLState())))) {
                    System.out.println("Derby shut down normally");
                } else {
                    System.err.println("Derby did not shut down normally");
                    se.printStackTrace();
                }}
        }}  
    public static int saveUrlFeed(UrlFeed urlFeed) {
        int pk = urlFeed.link.hashCode();
        loadDriver();
        Connection conn = null;
        ArrayList statements = new ArrayList(); 
        PreparedStatement psInsert = null;
        Statement s = null;
        ResultSet rs = null;
        try {
            String dbName = "UrlDB"; 
            conn = DriverManager.getConnection(protocol + dbName + ";create=true", props);
            rs = conn.createStatement().executeQuery("SELECT COUNT(id) FROM UrlFeed WHERE id = " + urlFeed.link.hashCode());           
            rs.next();
            int count = rs.getInt(1);           
            if (count == 0) {
                conn.setAutoCommit(false);
                s = conn.createStatement();
                statements.add(s);
                psInsert = conn.prepareStatement("INSERT INTO UrlFeed VALUES (?, ?, ?)");
                statements.add(psInsert);
                psInsert.setInt(1, pk);
                String escapeTitle = urlFeed.channelTitle.replaceAll("\'", "''");
                psInsert.setString(2, escapeTitle);
                psInsert.setString(3, urlFeed.link);
                psInsert.executeUpdate();
                conn.commit();
                System.out.println("Inserted " + urlFeed.channelTitle + " " + urlFeed.link);
                System.out.println("Committed the transaction");
            }
            shutdown();
        } catch (SQLException sqle) {
            sqle.printStackTrace();
        } finally {
            close(rs);
            int i = 0;
            while (!statements.isEmpty()) {
                Statement st = (Statement) statements.remove(i);
                close(st);
            }
            close(conn);
        }
        return pk;
    }
    private static void close(AutoCloseable closable) {
        try {
            if (closable != null) {
                closable.close();
                closable = null;
            }
        } catch (Exception sqle) {
            sqle.printStackTrace();
        }
    }
    private static void loadDriver() {     
            try {
                Class.forName(driver);
                System.out.println("Loaded driver");           
            } catch (Exception e) {
                e.printStackTrace();
            }    
    }
}
DisplayContentsFromDatabase.java

public class DisplayContentsFromDatabase extends Application {
    @Override public void start(Stage stage) {
        Group root = new Group();
        Scene scene = new Scene(root, 640, 480, Color.WHITE);
        final Map<String, Hyperlink> hyperLinksMap = new TreeMap<>();      
        final WebView newsBrief = new WebView(); 
        final WebEngine webEngine = new WebEngine();
        final WebView websiteView = new WebView();      
        webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
            public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue){
                if (newValue != State.SUCCEEDED) {
                    return;
                }               
                UrlFeed urlFeed = parse(webEngine.getDocument(), webEngine.getLocation());
                hyperLinksMap.get(webEngine.getLocation()).setText(urlFeed.channelTitle);               
                StringBuilder urlSource = new StringBuilder();
                urlSource.append("<head>\n")
                         .append("</head>\n")
                         .append("<body>\n");
                urlSource.append("<b>")
                         .append(urlFeed.channelTitle)
                         .append(" (")
                         .append(urlFeed.news.size())
                         .append(")")
                         .append("</b><br />\n");
                 StringBuilder htmlArticleSb = new StringBuilder();
                for (NewsArticle article:urlFeed.news) {                   
                    htmlArticleSb.append("<hr />\n")
                         .append("<b>\n")
                         .append(article.title)
                         .append("</b><br />")
                         .append(article.pubDate)
                         .append("<br />")
                         .append(article.description)
                         .append("<br />\n")
                         .append("<input type=\"button\" onclick=\"alert('")
                            .append(article.link)
                            .append("')\" value=\"View\" />\n");
                }
                String content = urlSource.toString() + "<form>\n" + htmlArticleSb.toString() + "</form></body>\n";
                System.out.println(content);
                newsBrief.getEngine().loadContent(content);
                DBUtils.saveUrlFeed(urlFeed);
            }
        }); 
        newsBrief.getEngine().setOnAlert(new EventHandler<WebEvent<String>>(){
            public void handle(WebEvent<String> evt) {
                websiteView.getEngine().load(evt.getData());
            }
        });        
        SplitPane splitPane = new SplitPane();
        splitPane.prefWidthProperty().bind(scene.widthProperty());
        splitPane.prefHeightProperty().bind(scene.heightProperty());
        final VBox leftArea = new VBox(10);
        final TextField urlField = new TextField();
        urlField.setOnAction(new EventHandler<ActionEvent>(){
            public void handle(ActionEvent ae){
                String url = urlField.getText();
                final Hyperlink jfxHyperLink = createHyperLink(url, webEngine);
                hyperLinksMap.put(url, jfxHyperLink);
                HBox rowBox = new HBox(20);
                rowBox.getChildren().add(jfxHyperLink);
                leftArea.getChildren().add(rowBox);
                webEngine.load(url);
                urlField.setText("");
            }
        });     
        leftArea.getChildren().add(urlField);        
        List<UrlFeed> urlFeeds = DBUtils.loadFeeds();
        for (UrlFeed feed:urlFeeds) {
            HBox rowBox = new HBox(20);
            final Hyperlink jfxHyperLink = new Hyperlink(feed.channelTitle);
            jfxHyperLink.setUserData(feed);
            final String location = feed.link;
            hyperLinksMap.put(feed.link, jfxHyperLink);
            jfxHyperLink.setOnAction(new EventHandler<ActionEvent>() {
                    public void handle(ActionEvent evt) {
                        webEngine.load(location);
                    }
                }
            );
            rowBox.getChildren().add(jfxHyperLink);
            leftArea.getChildren().add(rowBox);            
        }                 
        scene.setOnDragOver(new EventHandler<DragEvent>() {
            @Override
            public void handle(DragEvent event) {
                Dragboard db = event.getDragboard();
                if (db.hasUrl()) {
                    event.acceptTransferModes(TransferMode.COPY);
                } else {
                    event.consume();
                }
            }
        }); 
        scene.setOnDragDropped(new EventHandler<DragEvent>() {
            @Override
            public void handle(DragEvent event) {
                Dragboard db = event.getDragboard();
                boolean success = false;
                HBox rowBox = new HBox(20);
                if (db.hasUrl()) {
                    if (!hyperLinksMap.containsKey(db.getUrl())) {                        
                        final Hyperlink jfxHyperLink = createHyperLink(db.getUrl(), webEngine);
                        hyperLinksMap.put(db.getUrl(), jfxHyperLink);
                        rowBox.getChildren().add(jfxHyperLink);
                        leftArea.getChildren().add(rowBox);
                    }
                    webEngine.load(db.getUrl());
                }    
                event.setDropCompleted(success);
                event.consume();
            }
        });        
        leftArea.setAlignment(Pos.TOP_LEFT);        
        SplitPane splitPane2 = new SplitPane();
        splitPane2.setOrientation(Orientation.VERTICAL);
        splitPane2.prefWidthProperty().bind(scene.widthProperty());
        splitPane2.prefHeightProperty().bind(scene.heightProperty());
        HBox centerArea = new HBox();     
        centerArea.getChildren().add(newsBrief);
        HBox rightArea = new HBox();
        rightArea.getChildren().add(websiteView);
        splitPane2.getItems().add(centerArea);
        splitPane2.getItems().add(rightArea);
        splitPane.getItems().add(leftArea);
        splitPane.getItems().add(splitPane2);
        newsBrief.prefWidthProperty().bind(scene.widthProperty());
        websiteView.prefWidthProperty().bind(scene.widthProperty());
        ObservableList<SplitPane.Divider> dividers = splitPane.getDividers();
        for (int i = 0; i < dividers.size(); i++) {
            dividers.get(i).setPosition((i + 1.0) / 3);
        }
        HBox hbox = new HBox();
        hbox.getChildren().add(splitPane);
        root.getChildren().add(hbox);       
        stage.setScene(scene);
        stage.show();       
    }
    private static UrlFeed parse(Document doc, String location) {        
        UrlFeed urlFeed = new UrlFeed();
        urlFeed.link = location;        
        urlFeed.channelTitle = doc.getElementsByTagName("title")
             .item(0)
             .getTextContent();
        NodeList items = doc.getElementsByTagName("item");
        for (int i=0; i<items.getLength(); i++){
            Map<String, String> childElements = new HashMap<>();
            NewsArticle article = new NewsArticle();
            for (int j=0; j<items.item(i).getChildNodes().getLength(); j++) {
                Node node = items.item(i).getChildNodes().item(j);
                childElements.put(node.getNodeName().toLowerCase(), node.getTextContent());
            }
            article.title = childElements.get("title");
            article.description = childElements.get("description");
            article.link = childElements.get("link");
            article.pubDate = childElements.get("pubdate");           
            urlFeed.news.add(article);
        }
        return urlFeed;
    }  
    private Hyperlink createHyperLink(String url, final WebEngine webEngine) {
        final Hyperlink jfxHyperLink = new Hyperlink("Loading News...");
        UrlFeed aFeed = new UrlFeed();
        aFeed.link = url;
        jfxHyperLink.setUserData(aFeed);
        jfxHyperLink.setOnAction(new EventHandler<ActionEvent>() {
            public void handle(ActionEvent evt) {
                UrlFeed urlFeed = (UrlFeed)jfxHyperLink.getUserData();
                webEngine.load(urlFeed.link);
            }
        });
        return jfxHyperLink;
    } 
    public static void main(String[] args){
        DBUtils.setupDb();
        Application.launch(args);
    }
}
class UrlFeed {
    int id;
    String channelTitle = "News...";
    String link;
    List<NewsArticle> news = new ArrayList<>();

    public String toString() {
        return "urlFeed{" + "id=" + id + ", channelTitle=" + channelTitle + ", link=" + link + ", news=" + news + '}';
    }
    public UrlFeed() {
    }
    public UrlFeed(String title, String link) {
        this.channelTitle = title;
        this.link = link;
    }
}
class NewsArticle {
    String title;
    String description;
    String link;
    String pubDate;
    public String toString() {
        return "NewsArticle{" + "title=" + title + ", description=" + description + ", link=" + link + ", pubDate=" + pubDate + ", enclosure=" + '}';
    }  
}

Solution

  • I copied your code and refactored it.

    Catching exceptions and only printing the stack trace means that the program will continue to run. If you can't load the JDBC driver, for example, then what's the point of continuing? The entire program depends on being able to interact with the database.

    Exceptions that you cannot recover from should cause the program to terminate. Either the exception is out of your control or it indicates a bug in your program.

    Note, however, that it is safe to ignore SQLException when you fail to close a Statement or ResultSet since the program should be able to continue even though the ResultSet/Statement was not closed.

    • Your JDBC code should use try-with-resources.
    • You can use class java.sql.DatabaseMetaData to check whether a table exists.
    • You only need to load the JDBC driver class once.
    • You should only shut down the database when the program terminates.

    Although WebEngine will successfully load the URL that you entered in the urlField, the value returned by method getLocation() may not be identical to what you entered and hence hyperLinksMap will not contain the key you search for. As a result hyperLinksMap.get(webEngine.getLocation()) will return null which means that the following line of your code will throw NullPointerException.

    hyperLinksMap.get(webEngine.getLocation()).setText(urlFeed.channelTitle);
    

    You should also handle the case where WebEngine fails to load the URL entered by the user.

    Here is the refactored code. Note that I made all the classes public classes.

    1. Class DisplayContentsFromDatabase
    import java.sql.SQLException;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.TreeMap;
    
    import org.w3c.dom.Document;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    
    import javafx.application.Application;
    import javafx.beans.value.ChangeListener;
    import javafx.beans.value.ObservableValue;
    import javafx.collections.ObservableList;
    import javafx.concurrent.Worker;
    import javafx.event.ActionEvent;
    import javafx.event.EventHandler;
    import javafx.geometry.Orientation;
    import javafx.geometry.Pos;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.scene.control.Hyperlink;
    import javafx.scene.control.SplitPane;
    import javafx.scene.control.TextField;
    import javafx.scene.input.DragEvent;
    import javafx.scene.input.Dragboard;
    import javafx.scene.input.TransferMode;
    import javafx.scene.layout.HBox;
    import javafx.scene.layout.VBox;
    import javafx.scene.paint.Color;
    import javafx.scene.web.WebEngine;
    import javafx.scene.web.WebEvent;
    import javafx.scene.web.WebView;
    import javafx.stage.Stage;
    
    public class DisplayContentsFromDatabase extends Application {
    
        @Override
        public void start(Stage stage) throws Exception {
            Group root = new Group();
            Scene scene = new Scene(root, 640, 480, Color.WHITE);
            final Map<String, Hyperlink> hyperLinksMap = new TreeMap<>();
            final WebView newsBrief = new WebView();
            final WebEngine webEngine = new WebEngine();
            final WebView websiteView = new WebView();
            webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
                public void changed(ObservableValue<? extends Worker.State> observable,
                                    Worker.State oldValue,
                                    Worker.State newValue) {
                    if (newValue != Worker.State.SUCCEEDED) {
                        System.out.println("Worker.State = " + newValue);
                        if (newValue == Worker.State.FAILED) {
                            System.out.println("Failed to load URL.");
                        }
                        return;
                    }
                    UrlFeed urlFeed = parse(webEngine.getDocument(), webEngine.getLocation());
                    String location = webEngine.getLocation();
                    System.out.println("Web location: " + location);
                    Hyperlink link = hyperLinksMap.get(location);
                    if (link == null) {
                        System.out.println("Web location mismatch.");
                        return;
                    }
                    link.setText(urlFeed.channelTitle);
                    StringBuilder urlSource = new StringBuilder();
                    urlSource.append("<head>\n").append("</head>\n").append("<body>\n");
                    urlSource.append("<b>").append(urlFeed.channelTitle).append(" (")
                            .append(urlFeed.news.size()).append(")").append("</b><br />\n");
                    StringBuilder htmlArticleSb = new StringBuilder();
                    for (NewsArticle article : urlFeed.news) {
                        htmlArticleSb.append("<hr />\n").append("<b>\n").append(article.title)
                                .append("</b><br />").append(article.pubDate).append("<br />")
                                .append(article.description).append("<br />\n")
                                .append("<input type=\"button\" onclick=\"alert('").append(article.link)
                                .append("')\" value=\"View\" />\n");
                    }
                    String content = urlSource.toString() + "<form>\n" + htmlArticleSb.toString()
                            + "</form></body>\n";
                    System.out.println(content);
                    newsBrief.getEngine().loadContent(content);
                    try {
                        DBUtils.saveUrlFeed(urlFeed);
                    }
                    catch (ClassNotFoundException | SQLException x) {
                        throw new RuntimeException(x);
                    }
                }
            });
            newsBrief.getEngine().setOnAlert(new EventHandler<WebEvent<String>>() {
                public void handle(WebEvent<String> evt) {
                    websiteView.getEngine().load(evt.getData());
                }
            });
            SplitPane splitPane = new SplitPane();
            splitPane.prefWidthProperty().bind(scene.widthProperty());
            splitPane.prefHeightProperty().bind(scene.heightProperty());
            final VBox leftArea = new VBox(10);
            final TextField urlField = new TextField();
            urlField.setOnAction(new EventHandler<ActionEvent>() {
                public void handle(ActionEvent ae) {
                    String url = urlField.getText();
                    final Hyperlink jfxHyperLink = createHyperLink(url, webEngine);
                    hyperLinksMap.put(url, jfxHyperLink);
                    HBox rowBox = new HBox(20);
                    rowBox.getChildren().add(jfxHyperLink);
                    leftArea.getChildren().add(rowBox);
                    webEngine.load(url);
                    urlField.setText("");
                }
            });
            leftArea.getChildren().add(urlField);
            List<UrlFeed> urlFeeds = DBUtils.loadFeeds();
            for (UrlFeed feed : urlFeeds) {
                HBox rowBox = new HBox(20);
                final Hyperlink jfxHyperLink = new Hyperlink(feed.channelTitle);
                jfxHyperLink.setUserData(feed);
                final String location = feed.link;
                hyperLinksMap.put(feed.link, jfxHyperLink);
                jfxHyperLink.setOnAction(new EventHandler<ActionEvent>() {
                    public void handle(ActionEvent evt) {
                        webEngine.load(location);
                    }
                });
                rowBox.getChildren().add(jfxHyperLink);
                leftArea.getChildren().add(rowBox);
            }
            scene.setOnDragOver(new EventHandler<DragEvent>() {
                @Override
                public void handle(DragEvent event) {
                    Dragboard db = event.getDragboard();
                    if (db.hasUrl()) {
                        event.acceptTransferModes(TransferMode.COPY);
                    }
                    else {
                        event.consume();
                    }
                }
            });
            scene.setOnDragDropped(new EventHandler<DragEvent>() {
                @Override
                public void handle(DragEvent event) {
                    Dragboard db = event.getDragboard();
                    boolean success = false;
                    HBox rowBox = new HBox(20);
                    if (db.hasUrl()) {
                        if (!hyperLinksMap.containsKey(db.getUrl())) {
                            final Hyperlink jfxHyperLink = createHyperLink(db.getUrl(), webEngine);
                            hyperLinksMap.put(db.getUrl(), jfxHyperLink);
                            rowBox.getChildren().add(jfxHyperLink);
                            leftArea.getChildren().add(rowBox);
                        }
                        webEngine.load(db.getUrl());
                    }
                    event.setDropCompleted(success);
                    event.consume();
                }
            });
            leftArea.setAlignment(Pos.TOP_LEFT);
            SplitPane splitPane2 = new SplitPane();
            splitPane2.setOrientation(Orientation.VERTICAL);
            splitPane2.prefWidthProperty().bind(scene.widthProperty());
            splitPane2.prefHeightProperty().bind(scene.heightProperty());
            HBox centerArea = new HBox();
            centerArea.getChildren().add(newsBrief);
            HBox rightArea = new HBox();
            rightArea.getChildren().add(websiteView);
            splitPane2.getItems().add(centerArea);
            splitPane2.getItems().add(rightArea);
            splitPane.getItems().add(leftArea);
            splitPane.getItems().add(splitPane2);
            newsBrief.prefWidthProperty().bind(scene.widthProperty());
            websiteView.prefWidthProperty().bind(scene.widthProperty());
            ObservableList<SplitPane.Divider> dividers = splitPane.getDividers();
            for (int i = 0; i < dividers.size(); i++) { dividers.get(i).setPosition((i + 1.0) / 3); }
            HBox hbox = new HBox();
            hbox.getChildren().add(splitPane);
            root.getChildren().add(hbox);
            stage.setScene(scene);
            stage.show();
        }
    
        public void stop() throws Exception {
            DBUtils.shutdown();
        }
    
        private static UrlFeed parse(Document doc, String location) {
            UrlFeed urlFeed = new UrlFeed();
            urlFeed.link = location;
            urlFeed.channelTitle = doc.getElementsByTagName("title").item(0).getTextContent();
            NodeList items = doc.getElementsByTagName("item");
            for (int i = 0; i < items.getLength(); i++) {
                Map<String, String> childElements = new HashMap<>();
                NewsArticle article = new NewsArticle();
                for (int j = 0; j < items.item(i).getChildNodes().getLength(); j++) {
                    Node node = items.item(i).getChildNodes().item(j);
                    childElements.put(node.getNodeName().toLowerCase(), node.getTextContent());
                }
                article.title = childElements.get("title");
                article.description = childElements.get("description");
                article.link = childElements.get("link");
                article.pubDate = childElements.get("pubdate");
                urlFeed.news.add(article);
            }
            return urlFeed;
        }
    
        private Hyperlink createHyperLink(String url, final WebEngine webEngine) {
            final Hyperlink jfxHyperLink = new Hyperlink("Loading News...");
            UrlFeed aFeed = new UrlFeed();
            aFeed.link = url;
            jfxHyperLink.setUserData(aFeed);
            jfxHyperLink.setOnAction(new EventHandler<ActionEvent>() {
                public void handle(ActionEvent evt) {
                    UrlFeed urlFeed = (UrlFeed) jfxHyperLink.getUserData();
                    webEngine.load(urlFeed.link);
                }
            });
            return jfxHyperLink;
        }
    
        public static void main(String[] args) {
            try {
                DBUtils.setupDb();
                Application.launch(args);
            }
            catch (Exception x) {
                x.printStackTrace();
            }
        }
    }
    
    1. Class DBUtil
    import java.sql.Connection;
    import java.sql.DatabaseMetaData;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Properties;
    
    public class DBUtils {
        final static Properties props = new Properties();
        static {
            props.put("user", "admin");
            props.put("password", "letmein");
        }
        private static boolean  loaded;
        private static String framework = "embedded";
        private static String driver = "org.apache.derby.jdbc.EmbeddedDriver";
        private static String protocol = "jdbc:derby:";
    
        public static void setupDb() throws ClassNotFoundException, SQLException {
            loadDriver();
            Statement s = null;
            ResultSet rs = null;
            String dbName = "UrlDB";
            try (Connection conn = DriverManager.getConnection(protocol + dbName + ";create=true",
                                                               props)) {
                System.out.println("Creating database " + dbName);
                DatabaseMetaData dbmd = conn.getMetaData();
                rs = dbmd.getTables(null, null, "URLFEED", null);
                boolean createTable = !rs.next();
                if (createTable) {
                    s = conn.createStatement();
                    s.execute("CREATE TABLE UrlFeed(ID INT, Title VARCHAR(255), Url VARCHAR(600))");
                    System.out.println("Created database table 'UrlFeed'.");
                }
                else {
                    System.out.println("Database table 'UrlFeed' already exists.");
                }
            }
            finally {
                if (rs != null) {
                    try {
                        rs.close();
                    }
                    catch (SQLException xSql) {
                        // Ignore.
                    }
                }
                if (s != null) {
                    try {
                        s.close();
                    }
                    catch (SQLException xSql) {
                        // Ignore.
                    }
                }
            }
        }
    
        public static List<UrlFeed> loadFeeds() throws ClassNotFoundException, SQLException {
            loadDriver();
            List<UrlFeed> feeds = new ArrayList<>();
            String dbName = "UrlDB";
            try (Connection conn = DriverManager.getConnection(protocol + dbName + ";create=true",
                                                               props);
                 Statement s = conn.createStatement();
                 ResultSet rs = s.executeQuery("SELECT ID, Title, Url FROM UrlFeed")) {
                while (rs.next()) {
                    String title = rs.getString("title");
                    String url = rs.getString("url");
                    UrlFeed urlFeed = new UrlFeed(title, url);
                    urlFeed.id = urlFeed.link.hashCode();
                    feeds.add(urlFeed);
                }
            }
            return feeds;
        }
    
        public static void shutdown() {
            if (framework.equals("embedded")) {
                try {
                    DriverManager.getConnection("jdbc:derby:;shutdown=true");
                }
                catch (SQLException se) {
                    if (((se.getErrorCode() == 50000) && ("XJ015".equals(se.getSQLState())))) {
                        System.out.println("Derby shut down normally");
                    }
                    else {
                        System.err.println("Derby did not shut down normally");
                        se.printStackTrace();
                    }
                }
            }
        }
    
        public static int saveUrlFeed(UrlFeed urlFeed) throws ClassNotFoundException, SQLException {
            int pk = urlFeed.link.hashCode();
            loadDriver();
            PreparedStatement psInsert = null;
            ResultSet rs = null;
            String dbName = "UrlDB";
            try (Connection conn = DriverManager.getConnection(protocol + dbName + ";create=true",
                                   props);
                 PreparedStatement s = conn.prepareStatement("SELECT COUNT(id) FROM UrlFeed WHERE id = ?")) {
                s.setInt(1, pk);
                rs = s.executeQuery();
                rs.next();
                int count = rs.getInt(1);
                if (count == 0) {
                    psInsert = conn.prepareStatement("INSERT INTO UrlFeed VALUES (?, ?, ?)");
                    psInsert.setInt(1, pk);
                    String escapeTitle = urlFeed.channelTitle.replaceAll("\'", "''");
                    psInsert.setString(2, escapeTitle);
                    psInsert.setString(3, urlFeed.link);
                    count = psInsert.executeUpdate();
                    System.out.println("Inserted " + urlFeed.channelTitle + " " + urlFeed.link);
                }
            }
            finally {
                close(rs);
                close(psInsert);
            }
            return pk;
        }
    
        private static void close(AutoCloseable closable) {
            try {
                if (closable != null) {
                    closable.close();
                    closable = null;
                }
            }
            catch (Exception sqle) {
                sqle.printStackTrace();
            }
        }
    
        private static void loadDriver() throws ClassNotFoundException {
            if (!loaded) {
                Class.forName(driver);
                System.out.println("Loaded driver");
                loaded = true;
            }
        }
    }
    
    1. Class UrlFeed
    import java.util.ArrayList;
    import java.util.List;
    
    public class UrlFeed {
        int id;
        String channelTitle = "News...";
        String link;
        List<NewsArticle> news = new ArrayList<>();
    
        public String toString() {
            return String.format("urlFeed{id=%s, channelTitle=%s, link=%s, news=%s}",
                                 id,
                                 channelTitle,
                                 link,
                                 news);
        }
    
        public UrlFeed() {
        }
    
        public UrlFeed(String title, String link) {
            this.channelTitle = title;
            this.link = link;
        }
    }
    
    1. Class NewsArticle
    public class NewsArticle {
        String title;
        String description;
        String link;
        String pubDate;
    
        public String toString() {
            return String.format("NewsArticle{title=%s, description=%s, link=%s, pubDate=%s, enclosure=}",
                                 title,
                                 description,
                                 link,
                                 pubDate);
        }
    }
    

    Currently the above code only prints to standard output. You should change that so that the user is made aware, via the GUI, of what the program is doing. For example, while the Web page is loading, you could display a progress indicator. And when WebEngine fails to load the entered URL, you could display an alert.

    EDIT

    In response to your comment, where you wrote:

    the webview doesn't seem to be loading in the bottom right. Any suggestions?

    I believe you are referring to local variable websiteView in method start of class DisplayContentsFromDatabase, i.e.

    final WebView websiteView = new WebView();
    

    The only part of your code that references that variable is as follows (also in method start):

    newsBrief.getEngine().setOnAlert(new EventHandler<WebEvent<String>>() {
        public void handle(WebEvent<String> evt) {
            websiteView.getEngine().load(evt.getData());
        }
    });
    

    Here is a quote from the javadoc of method setOnAlert:

    Sets the value of the property onAlert.
    Property Description:JavaScript alert handler property. This handler is invokedwhen a script running on the Web page calls the alert function.

    So you need to enter a URL for a Web page that contains JavaScript and that JavaScript displays an alert. Only then will the code try to load something and display it in websiteView. I beg your pardon, but I'm not going to try to test that code.