#StackBounty: #java #windows #gradle #javafx #javafx-gradle-plugin Can I add more start menu items to my program with JavaFX?

Bounty: 500

I’m using the JavaFX Gradle plugin to build my JavaFX application. Is it possible to add more than one start menu item to the finished installer?


Get this bounty!!!

#StackBounty: #java #proxy #jersey #jax-rs Jersey: call another API implementation in the background

Bounty: 50

I have a jax-rs API with three implementations (let’s call them mock, legacy and new). Now what I’d like is to create some sort of a proxy feature, which would work followingly:

  • let’s consider some two of these master and slave implementations.
  • a call to master implementation would be intercepted by this proxy, which would asynchronously call the slave implementation.
  • no matter what the result of slave would be, response to the original call would always come from master implementation.
  • the response would never be delayed (or affected at all) by the slave‘s result (hence the asynchronous point).

My idea was to somehow hijack jersey’s dispatching process (ideally at the point where the Invocable object and request arguments are already available and then use jersey’s extension Proxy client to call the other API. The problem is that I don’t know jersey’s internals all that well so I don’t know how to create such feature. But still, this should be possible, as for example jersey’s ConfiguredValidator has exactly the arguments I’d need in method validateResourceAndInputParams.

To summarize in somewhat-pseudo-code, the feature (working as a request filter of some sort) would do just about this:

void doFeature(Invocable invocable, Object[] args) {
     new Thread(() -> {
        try {
            jerseyClientProxyWrapper.call(invocable, args);
        } finally { /* loging etc */  }
    }).start();
}

Any idea how to create and register such feature?


Get this bounty!!!

#StackBounty: #java #javafx Java Navigation System for GUI in JavaFX

Bounty: 50

I am currently working on a project in Java, and I use JavaFX for the GUI of the System. Currently, I am in the designing phase of the system, where I am designing the look of the system as well as setting up the basic functionality like navigation. I would highly appreciate it if someone can review my simple navigation system and the code I have written so far. I would like to know:

  • Any bad practices I am following, and how would I improve them.
  • Any architectural issues in my program, and how would I rectify that issue.
  • Any techniques I could follow to keep my software more maintainable.
  • Any inefficiencies that can be optimised.
  • And any sort of points you have in your mind that I could follow to improve my software.
  • Anything that you can add to the list above would also highly help.

I also have a preloader for this application, I have provided the code just for the sake of completeness. This preloader was generated by NetBeans.

TeleMart_Preloader.java

/*
 * Program developed by Hassan Althaf.
 * Copyright © 2015, Hassan Althaf.
 * Website: http://hassanalthaf.com
 */
package telemart.preloader;

import javafx.application.Preloader;
import javafx.application.Preloader.ProgressNotification;
import javafx.application.Preloader.StateChangeNotification;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

/**
 * Simple Preloader Using the ProgressBar Control
 *
 * @author hassan
 */
public class TeleMart_Preloader extends Preloader {

    ProgressBar bar;
    Stage stage;

    private Scene createPreloaderScene() {
        bar = new ProgressBar();
        BorderPane p = new BorderPane();
        p.setCenter(bar);
        return new Scene(p, 300, 150);        
    }

    @Override
    public void start(Stage stage) throws Exception {
        this.stage = stage;
        stage.setScene(createPreloaderScene());        
        stage.show();
    }

    @Override
    public void handleStateChangeNotification(StateChangeNotification scn) {
        if (scn.getType() == StateChangeNotification.Type.BEFORE_START) {
            stage.hide();
        }
    }

    @Override
    public void handleProgressNotification(ProgressNotification pn) {
        bar.setProgress(pn.getProgress());
    }    

}

com.hassanalthaf.telemart.Main.java:

/*
 * Program developed by Hassan Althaf.
 * Copyright © 2015, Hassan Althaf.
 * Website: http://hassanalthaf.com
 */
package com.hassanalthaf.telemart;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

/**
 *
 * @author hassan
 */
public class Main extends Application {

    public static final String APPLICATION_TITLE = "TeleMart - ERP System";

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("views/MainView.fxml"));

        Scene scene = new Scene(root);

        stage.setScene(scene);
        stage.setResizable(false);
        stage.setTitle(Main.APPLICATION_TITLE);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

com.hassanalthaf.telemart.views.Dashboard.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.shape.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" fx:id="dashboard" prefHeight="400.0" prefWidth="600.0" stylesheets="@css/dashboard.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.hassanalthaf.telemart.viewmodels.DashboardViewModel">
   <children>
      <MenuBar maxWidth="600.0" minWidth="600.0" prefWidth="600.0">
        <menus>
          <Menu mnemonicParsing="false" text="File">
            <items>
              <MenuItem fx:id="homeMenuItem" mnemonicParsing="false" onAction="#menuItemClick" text="Home" />
                  <MenuItem fx:id="anotherPageMenuItem" mnemonicParsing="false" onAction="#menuItemClick" text="Another Page" />
                  <MenuItem fx:id="differentPageMenuItem" mnemonicParsing="false" onAction="#menuItemClick" text="Different Page" />
            </items>
          </Menu>
        </menus>
      </MenuBar>
      <AnchorPane fx:id="differentPage" layoutY="29.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" opacity="0.0" prefHeight="371.0" prefWidth="600.0">
         <children>
            <TextArea layoutX="155.0" layoutY="62.0" prefHeight="200.0" prefWidth="200.0" promptText="Page three" />
         </children>
      </AnchorPane>
      <AnchorPane fx:id="anotherPage" layoutY="29.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" opacity="0.0" prefHeight="371.0" prefWidth="600.0">
         <children>
            <TextField layoutX="180.0" layoutY="77.0" promptText="Page Two" />
         </children>
      </AnchorPane>
      <AnchorPane fx:id="home" layoutY="29.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="371.0" prefWidth="600.0">
         <children>
            <TextField layoutX="133.0" layoutY="150.0" text="First Page" />
         </children>
      </AnchorPane>
   </children>
</AnchorPane>

com.hassanalthaf.telemart.views.MainView.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" fx:id="mainWindow" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="350.0" prefWidth="600.0" stylesheets="@css/style.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.hassanalthaf.telemart.viewmodels.MainViewModel">
   <children>
      <Label layoutX="222.0" layoutY="35.0" styleClass="title" text="TeleMart" />
      <TextField layoutX="380.0" layoutY="160.0" onKeyPressed="#loginEnter" promptText="Username">
         <styleClass>
            <String fx:value="login-field" />
            <String fx:value="login-field" />
         </styleClass>
      </TextField>
      <PasswordField layoutX="380.0" layoutY="208.0" onKeyPressed="#loginEnter" promptText="Password" styleClass="login-field" />
      <Button layoutX="495.0" layoutY="256.0" mnemonicParsing="false" onMouseClicked="#loginClick" text="Login" />
      <Label layoutX="45.0" layoutY="113.0" styleClass="content" text="Welcome to TeleMart's Enterprise
Resource Planning System.
Please enter your login credentials
on the right so that we could verify
your identity. Also, please do not
share your login credentials with
anyone or use another person's
login credentials." textAlignment="CENTER" wrapText="true" />
      <Label layoutX="220.0" layoutY="309.0" styleClass="content" text="© 2015, Hassan Althaf." />
   </children>
</AnchorPane>

com.hassanalthaf.telemart.views.css.style.css:

/*
Program developed by Hassan Althaf.
Copyright © 2015, Hassan Althaf.
Website: http://hassanalthaf.com
*/
/* 
    Created on : Dec 19, 2015, 6:09:52 PM
    Author     : hassan
*/

@font-face {
    font-family: 'Lato-Regular';
    src: url('../fonts/Lato-Regular.ttf');
}

@font-face {
    font-family: 'Lato-Hairline';
    src: url('../fonts/Lato-Hairline.ttf');
}

.root {
    -fx-background-color: #2C3E50;
}

.title {
    -fx-font-family: 'Lato-Hairline';
    -fx-font-size: 30pt;
    -fx-text-fill: #FFFFFF;
}

.login-field {
    -fx-background-color: #FFFFFF;
    -fx-border-radius: 5pt;
    -fx-padding: 10px;
    -fx-border-width: 1pt;
    -fx-border-style: solid;
    -fx-border-color: #202D3A;
    -fx-background-insets: 2, 0, 0;
    -fx-font-family: 'Lato-Regular';
}

.button {
    -fx-background-color: #3498DB;
    -fx-text-fill: #FFFFFF;
    -fx-font-size: 11pt;
    -fx-padding: 8px;
    -fx-border-radius: 10pt;
}

.button:hover {
    -fx-background-color: #51A7E0;
}

.content {
    -fx-font-family: 'Lato-Regular';
    -fx-font-size: 11pt;
    -fx-text-fill: #FFFFFF;
}

com.hassanalthaf.telemart.views.css.dashboard.css:

/*
Program developed by Hassan Althaf.
Copyright © 2015, Hassan Althaf.
Website: http://hassanalthaf.com
*/
/* 
    Created on : Dec 19, 2015, 11:29:50 PM
    Author     : hassan
*/
@font-face {
    font-family: 'Lato-Regular';
    src: url('../fonts/Lato-Regular.ttf');
}

.menu-bar {
    -fx-background-color: #3498DB;
}

.menu:hover {
    -fx-background-color: #51A7E0;
}

.menu:showing {
    -fx-background-color: #2487C9;
}

.menu .label {
    -fx-text-fill: #FFFFFF;
    -fx-font-family: 'Lato-Regular';
    -fx-font-size: 10pt;
}

.menu-item {
    -fx-background-color: #FFFFFF;
}

.menu-item:hover {
    -fx-background-color: #51A7E0;
}

.menu-item .label {
    -fx-text-fill: #333333;
    -fx-font-family: 'Lato-Regular';
    -fx-font-size: 10pt;
}

.menu-item:hover .label {
    -fx-text-fill: #FFFFFF;
}

com.hassanalthaf.telemart.viewmodels.MainViewModel.java:

/*
 * Program developed by Hassan Althaf.
 * Copyright © 2015, Hassan Althaf.
 * Website: http://hassanalthaf.com
 */
package com.hassanalthaf.telemart.viewmodels;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;

/**
 *
 * @author hassan
 */
public class MainViewModel implements Initializable {

    @FXML
    private Parent mainWindow;

    @FXML
    private void loginClick(MouseEvent event) {
        try {
            this.openDashboard();
        } catch (IOException exception) {

        }
    }

    @FXML
    private void loginEnter(KeyEvent event) {
        if (event.getCode() == KeyCode.ENTER) {
            try {
                this.openDashboard();
            } catch (IOException exception) {
                exception.printStackTrace();
            }
        }
    }

    private void openDashboard() throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/com/hassanalthaf/telemart/views/Dashboard.fxml"));
        Parent dashboard = fxmlLoader.load();
        DashboardViewModel dashboardViewModel = fxmlLoader.getController();
        dashboardViewModel.show(this.mainWindow);
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }

}

com.hassanalthaf.telemart.viewmodels.DashboardViewModel.java:

/*
 * Program developed by Hassan Althaf.
 * Copyright © 2015, Hassan Althaf.
 * Website: http://hassanalthaf.com
 */
package com.hassanalthaf.telemart.viewmodels;

import com.hassanalthaf.telemart.Main;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

/**
 * FXML Controller class
 *
 * @author hassan
 */
public class DashboardViewModel implements Initializable {

    @FXML
    private Parent dashboard;

    @FXML
    private AnchorPane home;

    @FXML
    private AnchorPane anotherPage;

    @FXML
    private AnchorPane differentPage;

    private AnchorPane currentPage;

    private void changePage(AnchorPane page) {
        this.currentPage.setOpacity(0);
        this.currentPage = page;
        this.currentPage.toFront();
        this.currentPage.setOpacity(1);
    }

    public void menuItemClick(ActionEvent event) {
        Object source = (MenuItem)event.getSource();
        MenuItem clickedItem;

        if(source instanceof MenuItem) {
            clickedItem = (MenuItem)source;
        } else {
            return;
        }

        String id = clickedItem.getId();

        switch (id) {
            case "homeMenuItem":
                this.changePage(this.home);
                break;
            case "anotherPageMenuItem":
                this.changePage(this.anotherPage);
                break;
            case "differentPageMenuItem":
                this.changePage(this.differentPage);
                break;
            default:
                this.changePage(this.home);
                break;
        }
    }

    public void show(Parent main) {
        Scene scene = new Scene(this.dashboard);

        Stage stage = new Stage();
        stage.setScene(scene);
        stage.setTitle(Main.APPLICATION_TITLE);
        stage.setResizable(false);
        stage.show();

        Stage mainStage = (Stage)main.getScene().getWindow();
        mainStage.close();
    }

    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
        this.currentPage = this.home;
    }    

}

The entire source code with all the assets can be found here on GitHub.


Get this bounty!!!

#StackBounty: #java #algorithm #recursion #comparative-review #backtracking Two approaches to print all permutations – returning versus…

Bounty: 50

I have noticed many of the backtracking problems have two ways of solving.

One is to return “whatever’s the required list”, vs passing-through the “result” to every call and appending to it. What is the downside of returning (is it less memory/time efficient)? Example – To print all possible permutations, what makes this solution inefficient vs the second one.

public List<List<Integer>> perm(int[] nums){
    List<List<Integer>> result = new ArrayList<List<Integer>>();
    if(nums.length == 0){
        result.add(new ArrayList<Integer>());
        return result;        
    }
    for(int i= 0;i<nums.length;i++){
        int first = nums[i];
        int[] remnums = new int[nums.length-1];
        int j = 0;
        for(int cur : nums){
            if(cur != first){
                remnums[j] = cur;j++;
            }
        }
        List<List<Integer>> tmp = perm(remnums);

        for(List<Integer> t : tmp){
            t.add(0,first);

        }
        result.addAll(tmp);
    }
    return result;
}

2nd approach —

public List<List<Integer>> permute(int[] nums) {
   List<List<Integer>> list = new ArrayList<>();
   // Arrays.sort(nums); // not necessary
   backtrack(list, new ArrayList<>(), nums);
   return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums){
   if(tempList.size() == nums.length){
      list.add(new ArrayList<>(tempList));
   } else{
      for(int i = 0; i < nums.length; i++){ 
         if(tempList.contains(nums[i])) continue; // element already exists, skip
         tempList.add(nums[i]);
         backtrack(list, tempList, nums);
         tempList.remove(tempList.size() - 1);
      }
   }
} 


Get this bounty!!!

#StackBounty: #java #javafx #java-9 #java-module #javafx-9 How to add to JavaFX Scene stylesheet from another module in Java 9?

Bounty: 50

I have two JPMS modules:

  • module-a
  • module-b

In module-a I have something like:

public class MyAppplication extends Application {
   ....
   public static void addCss(String path) {
       stage.getScene().getStylesheets().add(path);
   }
}

In module-b I have CSS file which I want to add to MyApplication. How to do it in code in module-b? I can’t understand how to pass path from another module.

I mean in module-b:

...
MyApplication.addCss(???);
...

EDIT
In OSGi I used the following solution in bundle-b (assuming, that module-a was bundle-a, and module-b was bundle-b):

String pathInBundleB = "com/foo/package-in-bundle-b/file.css"
Bundle bundleB = FrameworkUtil.getBundle(this.getClass()).getBundleContext().getBundle();
MyApplication.addCss(bundleB.getEntry(pathInBundleB).toString());


Get this bounty!!!

#StackBounty: #java #activex #javabeans #ocx #java-binding JavaBeans ActiveX Bridge for Java 8?

Bounty: 100

There used to be a JavaBeans ActiveX Bridge but AFAIK this is no longer supported under Java 8.

I want to call my JavaBeans from Excel, so what is the way to go with Java 8?


Get this bounty!!!

#StackBounty: #java #performance #algorithm #swing #computational-geometry Java algorithm to declutter rectangles

Bounty: 100

I’ve been working on an algorithm to declutter rectangles. It seems to work fine when I have less than 1,000 rectangles, but becomes much slower when there are 10,000, which I believe to be because the algorithm is inefficient with large datasets. I’m looking to find ways to optimize to perform better with more rectangles.

The code I have is based on this algorithm (which is based on this SO answer from another similar question: https://stackoverflow.com/a/3266158/33863):


Find the center C of the bounding box of your rectangles.

For each rectangle R that overlaps another:

  • Define a movement vector v.
  • Find all the rectangles R’ that overlap R.
  • Add a vector to v proportional to the vector between the center of R and R’.
  • Add a vector to v proportional to the vector between C and the center of R.
  • Move R by v.
  • Repeat until nothing overlaps.

This incrementally moves the rectangles away from each other and the center of all the rectangles. This will terminate because the component of v from step 4 will eventually spread them out enough all by itself.


Here is the code I’m working with:

public class Rectangles extends JPanel {

    // Create sample rectangles laid out in frame
    List<Rectangle2D> rectangles = new ArrayList<Rectangle2D>();
    {
        // x,y,w,h
        // random rectangles
        rectangles.add(new Rectangle2D.Float(300, 50, 50, 50));
        rectangles.add(new Rectangle2D.Float(300, 50, 20, 50));
        rectangles.add(new Rectangle2D.Float(100, 100, 100, 50));
        rectangles.add(new Rectangle2D.Float(120, 200, 50, 50));
        rectangles.add(new Rectangle2D.Float(150, 130, 100, 100));
        rectangles.add(new Rectangle2D.Float(0, 100, 100, 50));
        rectangles.add(new Rectangle2D.Float(690, 229, 388, 114));
        rectangles.add(new Rectangle2D.Float(347, 341, 347, 425));
        rectangles.add(new Rectangle2D.Float(107, 515, 179, 158));
        rectangles.add(new Rectangle2D.Float(55, 487, 174, 153));
        rectangles.add(new Rectangle2D.Float(458, 553, 125, 128));
        rectangles.add(new Rectangle2D.Float(109, 566, 125, 128));
        rectangles.add(new Rectangle2D.Float(138, 166, 125, 128));


        int numRowsAndColumns = 20;
//      int numRowsAndColumns = 50;
//      int numRowsAndColumns = 100;
//      Add more rectangles
        for (int i = 0; i < numRowsAndColumns; i++) {
            for (int j = 0; j < numRowsAndColumns; j++) {
                rectangles.add(new Rectangle2D.Float(i * 20, j * 10, 25, 20));
            }
        }


        System.out.println("Num Rectangles " + rectangles.size());
    }

    //The list of rectangles that are drawn on the screen
    List<Rectangle2D> rectanglesToDraw;

    //reset the view back to the unaffected rectangles
    protected void reset() {
        rectanglesToDraw = rectangles;

        this.repaint();
    }

    //Given a rectangle, find the rectangles from the rectList that intersect with it
    private List<Rectangle2D> findIntersections(Rectangle2D rect, List<Rectangle2D> rectList) {

        ArrayList<Rectangle2D> intersections = new ArrayList<Rectangle2D>();

        for (Rectangle2D intersectingRect : rectList) {
            if (!rect.equals(intersectingRect) && intersectingRect.intersects(rect)) {
                intersections.add(intersectingRect);
            }
        }

        return intersections;
    }

    //main algorithm that attempts to declutter the rectangles.    
    protected void fix() {
        rectanglesToDraw = new ArrayList<Rectangle2D>();

        //make copies to keep original list unaffected
        for (Rectangle2D rect : rectangles) {
            Rectangle2D copyRect = new Rectangle2D.Double();
            copyRect.setRect(rect);
            rectanglesToDraw.add(copyRect);
        }

        // Find the center C of the bounding box of your rectangles.
        Rectangle2D surroundRect = surroundingRect(rectanglesToDraw);
        Point center = new Point((int) surroundRect.getCenterX(), (int) surroundRect.getCenterY());

        int numIterations = 0;

        int movementFactor = 10; //ideally would be 1

        boolean hasIntersections = true;

        //keep going until there are no intersections present    
        while (hasIntersections) {

            //initialize to false within the loop.  
            hasIntersections = false;

            for (Rectangle2D rect : rectanglesToDraw) {

                // Find all the rectangles R' that overlap R.
                List<Rectangle2D> intersectingRects = findIntersections(rect, rectanglesToDraw);

                if (intersectingRects.size() > 0) {

                    // Define a movement vector v.
                    Point movementVector = new Point(0, 0);

                    Point centerR = new Point((int) rect.getCenterX(), (int) rect.getCenterY());

                    // For each rectangle R that overlaps another.
                    for (Rectangle2D rPrime : intersectingRects) {
                        Point centerRPrime = new Point((int) rPrime.getCenterX(), (int) rPrime.getCenterY());

                        int xTrans = (int) (centerR.getX() - centerRPrime.getX());
                        int yTrans = (int) (centerR.getY() - centerRPrime.getY());

                        // Add a vector to v proportional to the vector between the center of R and R'.
                        movementVector.translate(xTrans < 0 ? -movementFactor : movementFactor,
                                yTrans < 0 ? -movementFactor : movementFactor);

                    }

                    int xTrans = (int) (centerR.getX() - center.getX());
                    int yTrans = (int) (centerR.getY() - center.getY());

                    // Add a vector to v proportional to the vector between C and the center of R.
                    movementVector.translate(xTrans < 0 ? -movementFactor : movementFactor,
                            yTrans < 0 ? -movementFactor : movementFactor);

                    // Move R by v.
                    rect.setRect(rect.getX() + movementVector.getX(), rect.getY() + movementVector.getY(),
                            rect.getWidth(), rect.getHeight());

                    // Repeat until nothing overlaps.
                    hasIntersections = true;
                }

            }

            numIterations++;

        }

        System.out.println("That took " + numIterations+ " iterations.");

        Rectangles.this.repaint();

    }

    //find the Bounding rectangle of the list of rectangles
    //by iterating over all rectangles and 
    //finding the top left and bottom right corners
    private Rectangle2D surroundingRect(List<Rectangle2D> rectangles) {

        Point topLeft = null;
        Point bottomRight = null;

        for (Rectangle2D rect : rectangles) {
            if (topLeft == null) {
                topLeft = new Point((int) rect.getMinX(), (int) rect.getMinY());
            } else {
                if (rect.getMinX() < topLeft.getX()) {
                    topLeft.setLocation((int) rect.getMinX(), topLeft.getY());
                }

                if (rect.getMinY() < topLeft.getY()) {
                    topLeft.setLocation(topLeft.getX(), (int) rect.getMinY());
                }
            }

            if (bottomRight == null) {
                bottomRight = new Point((int) rect.getMaxX(), (int) rect.getMaxY());
            } else {
                if (rect.getMaxX() > bottomRight.getX()) {
                    bottomRight.setLocation((int) rect.getMaxX(), bottomRight.getY());
                }

                if (rect.getMaxY() > bottomRight.getY()) {
                    bottomRight.setLocation(bottomRight.getX(), (int) rect.getMaxY());
                }
            }
        }

        return new Rectangle2D.Double(topLeft.getX(), topLeft.getY(), bottomRight.getX() - topLeft.getX(),
                bottomRight.getY() - topLeft.getY());
    }

    //Draws the rectangles in the frame from the rectanglesToDraw data structure  
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;

        for (Rectangle2D entry : rectanglesToDraw) {
            g2d.setStroke(new BasicStroke(1));
            // g2d.fillRect((int) entry.getX(), (int) entry.getY(), (int) entry.getWidth(),
            // (int) entry.getHeight());
            g2d.draw(entry);
        }

    }

    //create GUI components and display it to the user
    protected static void createAndShowGUI() {
        Rectangles rects = new Rectangles();

        rects.reset();

        JFrame frame = new JFrame("Rectangles");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.add(rects, BorderLayout.CENTER);

        JPanel buttonsPanel = new JPanel();

        JButton fix = new JButton("Fix");

        fix.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                long start = System.currentTimeMillis();
                rects.fix();
                long end = System.currentTimeMillis();

                System.out.println("That took "+TimeUnit.MILLISECONDS.convert(end - start, TimeUnit.MILLISECONDS)+ " ms");

            }
        });

        JButton resetButton = new JButton("Reset");

        resetButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                rects.reset();
            }
        });

        buttonsPanel.add(fix);
        buttonsPanel.add(resetButton);

        frame.add(buttonsPanel, BorderLayout.SOUTH);

        frame.setSize(1920, 900);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowGUI();

            }
        });
    }

}

Here are a couple of screenshots to illustrate what its doing:

Before:
Before

After:
After


Get this bounty!!!

#StackBounty: #java #github #egit #jgit Add a file inside a folder to Github using JGit or EGit – directory1myfile.txt

Bounty: 50

I was able to add a file to GitHub using org.eclipse.egit.github.core java library (and code sample is referred from here: https://gist.github.com/Detelca/2337731 )

But I am not able to give a path like “folder1myfile.txt” OR “folder1folder2myfile.txt”

I am trying to find a simple example to add a file under a folder and was not really able to find it.

Any help on this with an example?

Below is the code i am using: (configuration details like username, reponame are in the method addFileToGH() )

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.eclipse.egit.github.core.Blob;
import org.eclipse.egit.github.core.Commit;
import org.eclipse.egit.github.core.CommitUser;
import org.eclipse.egit.github.core.Reference;
import org.eclipse.egit.github.core.Repository;
import org.eclipse.egit.github.core.RepositoryCommit;
import org.eclipse.egit.github.core.Tree;
import org.eclipse.egit.github.core.TreeEntry;
import org.eclipse.egit.github.core.TypedResource;
import org.eclipse.egit.github.core.User;
import org.eclipse.egit.github.core.client.GitHubClient;
import org.eclipse.egit.github.core.service.CommitService;
import org.eclipse.egit.github.core.service.DataService;
import org.eclipse.egit.github.core.service.RepositoryService;
import org.eclipse.egit.github.core.service.UserService;

public class GHFileWriter {

    public static void main(String[] args) {
        try {
            new GHFileWriter().addFileToGH("myfile.txt", "some file content");
            //new GHFileWriter().addFolderToGH("folder1");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


    public boolean addFileToGH(String fileName, String fileContent) throws IOException{
        String userName = "myusername";
        String password = "mypassword";
        String repoName = "myrepository"; 
        String ownerName = "myusername";
        String email = "myemail@gmail.com";

        //Basic authentication
        GitHubClient client = new GitHubClient();
            client.setCredentials(userName, password);

        // create needed services
        RepositoryService repositoryService = new RepositoryService();
        CommitService commitService = new CommitService(client);
        DataService dataService = new DataService(client);

     // get some sha's from current state in git
        Repository repository =  repositoryService.getRepository(ownerName, repoName );
        String baseCommitSha = repositoryService.getBranches(repository).get(0).getCommit().getSha();
        RepositoryCommit baseCommit = commitService.getCommit(repository, baseCommitSha);
        String treeSha = baseCommit.getSha();

        // create new blob with data
        Blob blob = new Blob();
            blob.setContent( fileContent ).setEncoding(Blob.ENCODING_UTF8); //"["" + System.currentTimeMillis() + ""]").setEncoding(Blob.ENCODING_UTF8);
        String blob_sha = dataService.createBlob(repository, blob);
        Tree baseTree = dataService.getTree(repository, treeSha);
Collection<TreeEntry> entries = new ArrayList<TreeEntry>();

    // create new tree entry
    TreeEntry treeEntry = new TreeEntry();
        treeEntry.setPath( fileName );
        treeEntry.setMode(TreeEntry.MODE_BLOB);
        treeEntry.setType(TreeEntry.TYPE_BLOB);
        treeEntry.setSha(blob_sha);
        treeEntry.setSize(blob.getContent().length());

   /* //Code for adding folder, not working
TreeEntry folderEntry = new TreeEntry();
        folderEntry.setPath( "folder1" );
        folderEntry.setMode(TreeEntry.MODE_DIRECTORY);
        folderEntry.setType(TreeEntry.TYPE_TREE);
        folderEntry.setSha(blob_sha); //one of the possible issues
        //folderEntry.setSize(blob.getContent().length());

        entries.add(folderEntry);

*/              
entries.add(treeEntry);

        Tree newTree = dataService.createTree(repository, entries, baseTree.getSha()); //Issue is popped-up here, error is thrown here

     // create commit
        Commit commit = new Commit();
            commit.setMessage("Test commit at " + new Date(System.currentTimeMillis()).toLocaleString());
            commit.setTree(newTree);



            //Due to an error with github api we have to to all this
            //TODO: Make this better (another function)
            UserService userService = new UserService(client);
            User user = userService.getUser();

            CommitUser author = new CommitUser();
            Calendar now = Calendar.getInstance();

                author.setName( userName );
                author.setEmail(email);
            //author.setEmail(userService.getEmails().get(0));
                author.setDate(now.getTime());
                commit.setAuthor(author);
                commit.setCommitter(author);


        List<Commit> listOfCommits = new ArrayList<Commit>();
            listOfCommits.add(new Commit().setSha(baseCommitSha));
        // listOfCommits.containsAll(base_commit.getParents());
            commit.setParents(listOfCommits);
        // commit.setSha(base_commit.getSha());
        Commit newCommit = dataService.createCommit(repository, commit);

     // create resource
        TypedResource commitResource = new TypedResource();
        commitResource.setSha(newCommit.getSha());
        commitResource.setType(TypedResource.TYPE_COMMIT);
        commitResource.setUrl(newCommit.getUrl());

        //System.out.println("Committed file URL: "+ newCommit.getUrl());
     // get master reference and update it
        Reference reference = dataService.getReference(repository, "heads/master");
            reference.setObject(commitResource);
            dataService.editReference(repository, reference, true);

            if( newCommit.getUrl() != null || !newCommit.getUrl().equalsIgnoreCase("") ){
                return true;
            }
        //push.setCommits(commits);

        return false;
    }
}

Below is the error when i execute the above code.

org.eclipse.egit.github.core.client.RequestException: tree.sha
a3b93733a6dfd221c24e94d2ce52c25307910d73 is not a valid tree (422) at
org.eclipse.egit.github.core.client.GitHubClient.createException(GitHubClient.java:552)
at
org.eclipse.egit.github.core.client.GitHubClient.sendJson(GitHubClient.java:643)
at
org.eclipse.egit.github.core.client.GitHubClient.post(GitHubClient.java:757)
at
org.eclipse.egit.github.core.service.DataService.createTree(DataService.java:203)
at
com.apps.ui5.accelerator.writers.GHFileWriter.addFileToGH(GHFileWriter.java:87)
at
com.apps.ui5.accelerator.writers.GHFileWriter.main(GHFileWriter.java:30)

Edit: The error causing code is commented. The commented code starts with “//Code for adding folder, not working”

Possible issue is with this line of code: folderEntry.setSha(blob_sha);

The error is thrown at this line: Tree newTree = dataService.createTree(repository, entries, baseTree.getSha());


Edit(VonC response): Hi VonC, thanks a lot for your response.
JGit looks promising but i see below issues.

  1. I am running this as a service in a cloud instance where i dont know if i can rely on filerepo which is refererred in the cookbook example. If this works in cloud, i can consider that as a solution.
  2. The example is also adding a simple file but not a folder/directory.
  3. And I need to push changes to GitHub using a java program, not git commands. How can i do that?

Can you refer any example which is creating a folder? I tried below code for adding a folder but did not work!

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

import org.dstadler.jgit.helper.CookbookHelper;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.NoFilepatternException;
import org.eclipse.jgit.lib.Repository;


public class GHFolderWriter {

    public static void main(String[] args) throws IOException, NoFilepatternException, GitAPIException {
        // prepare a new test-repository
        try (Repository repository = CookbookHelper.createNewRepository()) {
            try (Git git = new Git(repository)) {
                //create folder
                File folder = new File(repository.getDirectory().getParent(), "folder1");
                if(!folder.createNewFile()) {
                    throw new IOException("Could not create folder " + folder);
                }

                // create the file
                File myfile = new File(folder, "testfile1.txt");
                if(!myfile.createNewFile()) {
                    throw new IOException("Could not create file " + myfile);
                }

                // Stage all files in the repo including new files
                git.add().addFilepattern(".").call();

                // and then commit the changes.
                git.commit()
                        .setMessage("Commit all changes including additions")
                        .call();

                try(PrintWriter writer = new PrintWriter(myfile)) {
                    writer.append("Hello, world!");
                }

                // Stage all changed files, omitting new files, and commit with one command
                git.commit()
                        .setAll(true)
                        .setMessage("Commit changes to all files")
                        .call();


                System.out.println("Committed all changes to repository at " + repository.getDirectory());
            }
        }

    }

}

It is throwing this error:

Exception in thread “main” java.io.IOException: Could not open file.
Reason : The system cannot find the path specified (path
C:UsersramgoodAppDataLocalTempTestGitRepository441020326444846897folder1testfile1.txt,
working dir C:Usersramgoodworkspace-sapui5-1.32accelerate) at
java.io.WinNTFileSystem.createFileExclusively(Native Method) at
java.io.File.createNewFile(File.java:1016) at
com.apps.ui5.accelerator.writers.GHFolderWriter.main(GHFolderWriter.java:37)

Edit(3): I moved to jgit as you suggested and below is my new program. I am able to 1. clone remote repo with my local repo 2. add a folder and file to local repo and commit locally but 3. Failing to push to github.

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;



/**
 * Note: This snippet is not done and likely does not show anything useful yet
 *
 * @author dominik.stadler at gmx.at
 */
public class PushToRemoteRepository {

    private static final String REMOTE_URL = "https://github.com/debsap/testrepo.git";

    public static void main(String[] args) throws IOException, GitAPIException {
        // prepare a new folder for the cloned repository
        File localPath = File.createTempFile("REStGitRepository", "");
        if(!localPath.delete()) {
            throw new IOException("Could not delete temporary file " + localPath);
        }

        // then clone
        System.out.println("Cloning from " + REMOTE_URL + " to " + localPath);
        try (Git git = Git.cloneRepository()
                .setURI(REMOTE_URL)
                .setCredentialsProvider(new UsernamePasswordCredentialsProvider("debsap", "testpasword1"))
                .setDirectory(localPath)
                .call()) {

            Repository repository = git.getRepository();
            // create the folder
            File theDir = new File(repository.getDirectory().getParent(), "dir1");
            theDir.mkdir();

         // create the file
            File myfile = new File(theDir, "testfile2.txt");
            if(!myfile.createNewFile()) {
                throw new IOException("Could not create file " + myfile);
            }

            // Stage all files in the repo including new files
            git.add().addFilepattern(".").call();

            // and then commit the changes.
            git.commit().setMessage("Commit all changes including additions").call();

            try(PrintWriter writer = new PrintWriter(myfile)) {
                writer.append("Hello, world!");
            }
            // Stage all changed files, omitting new files, and commit with one command
            git.commit()
                    .setAll(true)
                    .setMessage("Commit changes to all files")
                    .call();
         // now open the created repository
            FileRepositoryBuilder builder = new FileRepositoryBuilder();
            try (Repository repository1 = builder.setGitDir(localPath)
                    .readEnvironment() // scan environment GIT_* variables
                    .findGitDir() // scan up the file system tree
                    .build()) {

                try (Git git1 = new Git(repository1)) {
                    git1.push().call();
                }
                System.out.println("Pushed from repository: " + repository1.getDirectory() + " to remote repository at " + REMOTE_URL);
            }
        }
    }
}

I am getting below error while trying to push to remote repo or github.

Cloning from https://github.com/debsap/testrepo.git to
C:UsersramgoodAppDataLocalTempREStGitRepository8321744366017013430
Exception in thread “main”
org.eclipse.jgit.api.errors.TransportException: origin: not found. at
org.eclipse.jgit.api.PushCommand.call(PushCommand.java:183) at
org.dstadler.jgit.unfinished.PushToRemoteRepository.main(PushToRemoteRepository.java:88)
Caused by: org.eclipse.jgit.errors.NoRemoteRepositoryException:
origin: not found. at
org.eclipse.jgit.transport.TransportLocal$1.open(TransportLocal.java:131)
at
org.eclipse.jgit.transport.TransportBundleFile$1.open(TransportBundleFile.java:106)
at org.eclipse.jgit.transport.Transport.open(Transport.java:565) at
org.eclipse.jgit.transport.Transport.openAll(Transport.java:383) at
org.eclipse.jgit.api.PushCommand.call(PushCommand.java:147) … 1
more

Below is the config file from .git folder. Note that i cannot edit this manually and should be updated through java program only.

[core] symlinks = false repositoryformatversion = 0 filemode =
false logallrefupdates = true [remote “origin”] url =
https://github.com/debsap/testrepo.git fetch =
+refs/heads/:refs/remotes/origin/ [branch “master”] remote = origin merge = refs/heads/master

Thanks in advance.


Get this bounty!!!

#StackBounty: #java #multithreading #tomcat #tomcat7 #jvisualvm Memory leak when redeploying application in Tomcat

Bounty: 50

I have WebApplication which is deployed in Tomcat 7.0.70. I simulated the following situation:

  1. I created the heap dump.
  2. Then I sent the Http request and in service’s method I printed the current thread and its classLoader. And then I invoked Thread.currentThread.sleep(10000).
  3. And at the same moment I clicked ‘undeploy this application’ in Tomcat’s admin page.
  4. I created new heap dump.
  5. After some minutes I created new hep dump.

RESULTS

Thread dump

On the following screen you can see that after I clicked “redeploy”, all threads (which were associated with this web application) were killed except the thread “http-apr-8081-exec-10”. As I set Tomcat’s attribute “renewThreadsWhenStoppingContext == true”, so you can see that after some time this thread (“http-apr-8081-exec-10”) was killed and new thread (http-apr-8081-exec-11) was created instead of it. So I didn’t expect to have the old WCL after creation of heap dump 3, because there are not any old threads or objects.

enter image description here

Heapd dump 1

On the following two screens you can see that when the application was running there was only one WCL(its parameter “started” = true).
And the thread “http-apr-8081-exec-10” had the contextClassLoader = URLClassLoader ( because it was in the Tomcat’s pool).
I’m speaking only about this thread because you will able to see that this thread will handle my future HTTP request.

enter image description here

enter image description here

Sending HTTP request

Now I send the HTTP request and in my code I get information about the current thread.You can see that my request is being handled by the thread “http-apr-8081-exec-10”

дек 23, 2016 9:28:16 AM c.c.c.f.s.r.ReportGenerationServiceImpl INFO:  request has been handled in 
   thread = http-apr-8081-exec-10,  its contextClassLoader = WebappClassLoader
   context: /hdi
   delegate: false
   repositories:
   /WEB-INF/classes/
   ----------> Parent Classloader: java.net.URLClassLoader@4162ca06

Then I click “Redeploy my web application” and I get the following message in console.

 дек 23, 2016 9:28:27 AM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
 SEVERE: The web application [/hdi] appears to have started a thread named [http-apr-8081-exec-10] but has failed to stop it. This is very likely to create a memory leak.

Heapd dump 2

On the following screens you can see that there are two instances WebAppClassLoader. One of them( number #1) is old( its attribute “started” = false).
And the WCL #2 was created after redeploying application (its attribute “started” = true).
And the thread we review has contextClassLoader = “org.apache.catalina.loader.WebappClassLoader”.
Why? I expected to see contextClassLoader = “java.net.URLClassLoader” (after all, when any thread finishes its work it is returned to the Tomcat’s pool
and its attribute “contextClassLoader” is set to any base classloader).

enter image description here

enter image description here

enter image description here

Heapd dump 3

You can see that there isn’t thread “http-apr-8081-exec-10”, but there is thread “http-apr-8081-exec-11” and it has contextClassLoader = “WebappClassLoader”
(Why not URLClassLoader?).

In the end we have the following: there is thread “http-apr-8081-exec-11” which has the ref to the WebappClassLoader #1.
And obviosly when I make “Nearest GC Root” on the WCL #1 I will see the ref to the thread 11.

enter image description here

enter image description here

Questions.

How can I forcibly say to Tomcat to return old value contextClassLoader (URLClassLoader) after thread will finish its work?

How can I make sure Tomcat doesn’t copy old value “contextClassLoader” during the thread renewal?

Maybe, do you know other way to resolve my problem?


Get this bounty!!!

#StackBounty: #java #linux #spring-boot #log4j How to Extern log4j.properties file with Spring Boot Microservice and Run It As a Linux …

Bounty: 100

Have a Spring Boot (1.5.4.RELEASE) based microservice which I deploy a jar to an AWS EC Instance (Linux environment). Now, I am also deploying an external log4j.properties file so I have to start the microservice like this:

java -jar myapp.jar -Dlogging.config=/path/to/log4j.properties

How can I configure this Spring Boot Microservice as a Linux service where I can start and stop it using these flags:

sudo service myapp start | stop | status | restart

Thank you very much.


Get this bounty!!!