Compare commits
98 Commits
revert-146
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83209e30f9 | ||
|
|
9fd719365b | ||
|
|
4eb7bef34b | ||
|
|
dcccf2eda7 | ||
|
|
97dd38eb79 | ||
|
|
7907282829 | ||
|
|
9ad7d24c9e | ||
|
|
a5eb9418c8 | ||
|
|
65e31eaf04 | ||
|
|
20e135aea1 | ||
|
|
1691ad32b6 | ||
|
|
0c87b2a3bf | ||
|
|
23681f9e1e | ||
|
|
5fe1c28e51 | ||
|
|
25c0f9b685 | ||
|
|
41829046c5 | ||
|
|
fb99901305 | ||
|
|
b6f4803197 | ||
|
|
1d3fa127f4 | ||
|
|
c9b87071ab | ||
|
|
09f2a5c584 | ||
|
|
951856e2cc | ||
|
|
a9f54033d5 | ||
|
|
55ba37d848 | ||
|
|
b724c59c38 | ||
|
|
e02964ff81 | ||
|
|
2b6ee3104d | ||
|
|
3e450193dd | ||
|
|
7217ee5e0c | ||
|
|
7588462856 | ||
|
|
b0998fd931 | ||
|
|
273a20e8e5 | ||
|
|
8f5965b7e8 | ||
|
|
ff430e69d5 | ||
|
|
b3fdbcb76f | ||
|
|
5311e96930 | ||
|
|
5b2dd26fa3 | ||
|
|
293206c419 | ||
|
|
ff7e5bad9b | ||
|
|
f1feec3922 | ||
|
|
300f1f3816 | ||
|
|
f4bb7bf36f | ||
|
|
936fad8c02 | ||
|
|
5983194d95 | ||
|
|
2e70b5cd87 | ||
|
|
e8bce0690e | ||
|
|
2b422a9ba1 | ||
|
|
6f9cda355d | ||
|
|
3dc7772f1f | ||
|
|
942e8f4932 | ||
|
|
ba2854ef9e | ||
|
|
078a09393a | ||
|
|
573f511bb3 | ||
|
|
0dba825b34 | ||
|
|
31046a3ae2 | ||
|
|
18e5ca49de | ||
|
|
6cadb7c902 | ||
|
|
8897d1a81d | ||
|
|
4bd2e1eedb | ||
|
|
911ff75935 | ||
|
|
862e85c92c | ||
|
|
527c797381 | ||
|
|
e4d766b808 | ||
|
|
9363253c81 | ||
|
|
d4a7abdd49 | ||
|
|
dac91ce751 | ||
|
|
b077616346 | ||
|
|
0d2c280b7f | ||
|
|
0529c7f612 | ||
|
|
a879aceef7 | ||
|
|
07e0abff43 | ||
|
|
bc8d43ce09 | ||
|
|
9e9182125d | ||
|
|
0685a8702c | ||
|
|
ee4b4ce003 | ||
|
|
664e9d1932 | ||
|
|
bb1d29302b | ||
|
|
1298e1d4f7 | ||
|
|
b738c458ac | ||
|
|
2423f086f6 | ||
|
|
6fe37fca81 | ||
|
|
53572725ad | ||
|
|
7fbae56aa6 | ||
|
|
a3127e5f36 | ||
|
|
df4a024ed9 | ||
|
|
f4f979b6f8 | ||
|
|
652804a1a9 | ||
|
|
a1239f9a87 | ||
|
|
8dfae82f04 | ||
|
|
67ecc95a5b | ||
|
|
6e7b87c158 | ||
|
|
3bb7d4b8e6 | ||
|
|
dbbf86a134 | ||
|
|
00a7141670 | ||
|
|
081bfeac8d | ||
|
|
ca1cf088fa | ||
|
|
0e90b0bab5 | ||
|
|
6044c33bbf |
@@ -0,0 +1,2 @@
|
||||
## Relevant Articles
|
||||
- [Understanding XSLT Processing in Java](https://www.baeldung.com/java-extensible-stylesheet-language-transformations)
|
||||
|
||||
@@ -10,3 +10,4 @@ This module contains articles about Simple Storage Service (S3) on AWS
|
||||
- [Check if a Specified Key Exists in a Given S3 Bucket Using Java](https://www.baeldung.com/java-aws-s3-check-specified-key-exists)
|
||||
- [Listing All AWS S3 Objects in a Bucket Using Java](https://www.baeldung.com/java-aws-s3-list-bucket-objects)
|
||||
- [Update an Existing Amazon S3 Object Using Java](https://www.baeldung.com/java-update-amazon-s3-object)
|
||||
- [How To Rename Files and Folders in Amazon S3](https://www.baeldung.com/java-amazon-s3-rename-files-folders)
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
package reminderapplication;
|
||||
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.Insets;
|
||||
|
||||
public class ConstraintsBuilder {
|
||||
|
||||
static GridBagConstraints constraint(int x, int y) {
|
||||
final GridBagConstraints gridBagConstraints = new GridBagConstraints();
|
||||
gridBagConstraints.gridx = x;
|
||||
gridBagConstraints.gridy = y;
|
||||
gridBagConstraints.insets = new Insets(5, 5, 5, 5);
|
||||
return gridBagConstraints;
|
||||
}
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
package reminderapplication;
|
||||
|
||||
import static reminderapplication.ConstraintsBuilder.*;
|
||||
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.HeadlessException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
public class EditReminderFrame extends JFrame {
|
||||
|
||||
private static Timer TIMER = new Timer();
|
||||
|
||||
private final TimeReminderApplication reminderApplication;
|
||||
private final JLabel reminderTextLabel;
|
||||
private final JLabel repeatPeriodLabel;
|
||||
private final JLabel setDelayLabel;
|
||||
private final JComboBox<Integer> delay;
|
||||
private final JComboBox<Integer> period;
|
||||
private final JButton cancelButton;
|
||||
private final JButton okButton;
|
||||
private final JTextField textField;
|
||||
private final JLabel delaysLabel;
|
||||
private final JLabel periodLabel;
|
||||
|
||||
private final int reminderIndex;
|
||||
|
||||
public EditReminderFrame(TimeReminderApplication reminderApp, String reminderText, int delayInSeconds, int periodInSeconds, int index) throws HeadlessException {
|
||||
this.reminderApplication = reminderApp;
|
||||
reminderIndex = index;
|
||||
textField = createTextField(reminderText);
|
||||
delay = createDelayComboBox(delayInSeconds);
|
||||
period = createPeriodComboBox(periodInSeconds);
|
||||
cancelButton = createCancelButton();
|
||||
okButton = createOkButton();
|
||||
reminderTextLabel = createReminderTextLabel();
|
||||
repeatPeriodLabel = createRepeatPeriodLabel();
|
||||
setDelayLabel = createSetDelayLabel();
|
||||
delaysLabel = createDelaysLabel();
|
||||
periodLabel = createPeriodLabel();
|
||||
configureVisualRepresentation();
|
||||
configureActions();
|
||||
}
|
||||
|
||||
private void configureActions() {
|
||||
updateReminder();
|
||||
}
|
||||
|
||||
private void configureVisualRepresentation() {
|
||||
configureFrame();
|
||||
setLocationRelativeTo(null);
|
||||
setLayout(new GridBagLayout());
|
||||
add(reminderTextLabel, constraint(0,0));
|
||||
add(repeatPeriodLabel, constraint(1,0));
|
||||
add(setDelayLabel, constraint(2,0));
|
||||
add(textField, constraint(0, 1));
|
||||
add(delay, constraint(1, 1));
|
||||
add(period, constraint(2, 1));
|
||||
add(delaysLabel, constraint(1,3));
|
||||
add(periodLabel, constraint(2,3));
|
||||
add(okButton, constraint(1, 4));
|
||||
add(cancelButton, constraint(2, 4));
|
||||
pack();
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
private void configureFrame() {
|
||||
setTitle("Set Reminder");
|
||||
setName("Set Reminder");
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
}
|
||||
|
||||
private static JLabel createSetDelayLabel() {
|
||||
return createLabel("Set Delay", "Set Delay Label");
|
||||
}
|
||||
|
||||
private static JLabel createRepeatPeriodLabel() {
|
||||
return createLabel("Set Period", "Set Repeat Period Label");
|
||||
}
|
||||
|
||||
private static JLabel createReminderTextLabel() {
|
||||
return createLabel("Reminder Text", "Reminder Text Label");
|
||||
}
|
||||
|
||||
private JLabel createPeriodLabel() {
|
||||
return createLabel("0", "Period label");
|
||||
}
|
||||
|
||||
private JLabel createDelaysLabel() {
|
||||
return createLabel("30", "Delays Label");
|
||||
}
|
||||
|
||||
private JComboBox<Integer> createPeriodComboBox(final int periodInSeconds) {
|
||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20}));
|
||||
comboBox.setSelectedItem(periodInSeconds);
|
||||
comboBox.setName("set Period");
|
||||
comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString()));
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private JComboBox<Integer> createDelayComboBox(final int delayInSeconds) {
|
||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5}));
|
||||
comboBox.setSelectedItem(delayInSeconds);
|
||||
comboBox.setName("set Delay");
|
||||
comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString()));
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private JTextField createTextField(final String reminderText) {
|
||||
final JTextField textField = new JTextField(20);
|
||||
textField.setName("Field");
|
||||
textField.setText(reminderText);
|
||||
return textField;
|
||||
}
|
||||
|
||||
private JButton createOkButton() {
|
||||
final JButton button = new JButton("ok");
|
||||
button.setName("OK");
|
||||
return button;
|
||||
}
|
||||
|
||||
private void updateReminder() {
|
||||
okButton.addActionListener(e -> this.dispose());
|
||||
okButton.addActionListener(e -> {
|
||||
final int periodInSeconds = getTimeInSeconds(period);
|
||||
final int delayInSeconds = getTimeInSeconds(delay);
|
||||
final Reminder reminder = new Reminder(textField.getText(), delayInSeconds, periodInSeconds);
|
||||
((DefaultListModel<Reminder>) reminderApplication.getReminders()).set(reminderIndex, reminder);
|
||||
});
|
||||
okButton.addActionListener(e -> scheduleReminder(textField, delay, period));
|
||||
}
|
||||
|
||||
private void scheduleReminder(final JTextField textField, final JComboBox<Integer> delay, final JComboBox<Integer> period) {
|
||||
final int periodInSeconds = getTimeInSeconds(period);
|
||||
if (periodInSeconds == 0)
|
||||
scheduleNonRepeatedReminder(textField, delay);
|
||||
else
|
||||
scheduleRepeatedReminder(textField, delay, period);
|
||||
}
|
||||
|
||||
private void scheduleRepeatedReminder(final JTextField textField, final JComboBox<Integer> delay, final JComboBox<Integer> period) {
|
||||
final int delayInSeconds = getTimeInSeconds(delay);
|
||||
final int periodInSeconds = getTimeInSeconds(period);
|
||||
final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds);
|
||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds), TimeUnit.SECONDS.toMillis(periodInSeconds));
|
||||
}
|
||||
|
||||
private void scheduleNonRepeatedReminder(final JTextField textField, final JComboBox<Integer> delay) {
|
||||
final int delayInSeconds = getTimeInSeconds(delay);
|
||||
final int periodInSeconds = 0;
|
||||
final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds);
|
||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds));
|
||||
|
||||
}
|
||||
|
||||
private int getTimeInSeconds(final JComboBox<Integer> comboBox) {
|
||||
if (comboBox != null && comboBox.getSelectedItem() != null)
|
||||
return ((Integer) comboBox.getSelectedItem());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
private TimerTask getTimerTask(final String reminderText, final Integer delayInSeconds, final Integer periodInSeconds) {
|
||||
return new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
new ReminderPopupFrame(reminderApplication, reminderText, delayInSeconds, periodInSeconds);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private JButton createCancelButton() {
|
||||
final JButton button = new JButton("cancel");
|
||||
button.setName("Cancel");
|
||||
button.addActionListener(e -> this.dispose());
|
||||
return button;
|
||||
}
|
||||
|
||||
private static JLabel createLabel(final String text, final String name) {
|
||||
JLabel label = new JLabel(text);
|
||||
label.setName(name);
|
||||
return label;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package reminderapplication;
|
||||
|
||||
public class Reminder {
|
||||
|
||||
private static String REMINDER_FORMAT = "Reminder Text: %s; Delay: %d; Period: %d;";
|
||||
|
||||
private final String name;
|
||||
private final int delay;
|
||||
private final int period;
|
||||
|
||||
public Reminder(final String name, final int delay, final int period) {
|
||||
this.name = name;
|
||||
this.delay = delay;
|
||||
this.period = period;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getDelay() {
|
||||
return delay;
|
||||
}
|
||||
|
||||
public int getPeriod() {
|
||||
return period;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return REMINDER_FORMAT.formatted(name, delay, period);
|
||||
}
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
package reminderapplication;
|
||||
|
||||
import static reminderapplication.ConstraintsBuilder.*;
|
||||
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.HeadlessException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
public class ReminderFrame extends JFrame {
|
||||
|
||||
private static Timer TIMER = new Timer();
|
||||
private final TimeReminderApplication reminderApplication;
|
||||
private final JLabel reminderTextLabel;
|
||||
private final JLabel repeatPeriodLabel;
|
||||
private final JLabel setDelayLabel;
|
||||
private final JComboBox<Integer> delay;
|
||||
private final JComboBox<Integer> period;
|
||||
private final JButton cancelButton;
|
||||
private final JButton okButton;
|
||||
private final JTextField textField;
|
||||
private final JLabel delaysLabel;
|
||||
private final JLabel periodLabel;
|
||||
|
||||
public ReminderFrame(TimeReminderApplication reminderApp) throws HeadlessException {
|
||||
this.reminderApplication = reminderApp;
|
||||
textField = createTextField();
|
||||
delay = createDelayComboBox();
|
||||
period = createPeriodComboBox();
|
||||
cancelButton = createCancelButton();
|
||||
okButton = createOkButton();
|
||||
reminderTextLabel = createReminderTextLabel();
|
||||
repeatPeriodLabel = createRepeatPeriodLabel();
|
||||
setDelayLabel = createSetDelayLabel();
|
||||
delaysLabel = createDelaysLabel();
|
||||
periodLabel = createPeriodLabel();
|
||||
configureVisualRepresentation();
|
||||
configureActions();
|
||||
}
|
||||
|
||||
private void configureActions() {
|
||||
createNewReminder();
|
||||
}
|
||||
|
||||
private void configureVisualRepresentation() {
|
||||
configureFrame();
|
||||
setLocationRelativeTo(null);
|
||||
setLayout(new GridBagLayout());
|
||||
add(reminderTextLabel, constraint(0,0));
|
||||
add(repeatPeriodLabel, constraint(1,0));
|
||||
add(setDelayLabel, constraint(2,0));
|
||||
add(textField, constraint(0, 1));
|
||||
add(delay, constraint(1, 1));
|
||||
add(period, constraint(2, 1));
|
||||
add(delaysLabel, constraint(1,3));
|
||||
add(periodLabel, constraint(2,3));
|
||||
add(okButton, constraint(1, 4));
|
||||
add(cancelButton, constraint(2, 4));
|
||||
pack();
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
private void configureFrame() {
|
||||
setTitle("Set Reminder");
|
||||
setName("Set Reminder");
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
}
|
||||
|
||||
private static JLabel createSetDelayLabel() {
|
||||
return createLabel("Set Delay", "Set Delay Label");
|
||||
}
|
||||
|
||||
private static JLabel createRepeatPeriodLabel() {
|
||||
return createLabel("Set Period", "Set Repeat Period Label");
|
||||
}
|
||||
|
||||
private static JLabel createReminderTextLabel() {
|
||||
return createLabel("Reminder Text", "Reminder Text Label");
|
||||
}
|
||||
|
||||
private JLabel createPeriodLabel() {
|
||||
return createLabel("0", "Period label");
|
||||
}
|
||||
|
||||
private JLabel createDelaysLabel() {
|
||||
return createLabel("30", "Delays Label");
|
||||
}
|
||||
|
||||
private JComboBox<Integer> createPeriodComboBox() {
|
||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20}));
|
||||
comboBox.setName("set Period");
|
||||
comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString()));
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private JComboBox<Integer> createDelayComboBox() {
|
||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5}));
|
||||
comboBox.setName("set Delay");
|
||||
comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString()));
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private JTextField createTextField() {
|
||||
final JTextField textField = new JTextField(20);
|
||||
textField.setName("Field");
|
||||
return textField;
|
||||
}
|
||||
|
||||
private JButton createOkButton() {
|
||||
final JButton button = new JButton("ok");
|
||||
button.setName("OK");
|
||||
return button;
|
||||
}
|
||||
|
||||
private void createNewReminder() {
|
||||
|
||||
okButton.addActionListener(e -> this.dispose());
|
||||
okButton.addActionListener(e -> {
|
||||
final int periodInSeconds = getTimeInSeconds(period);
|
||||
final int delayInSeconds = getTimeInSeconds(delay);
|
||||
final Reminder reminder = new Reminder(textField.getText(), delayInSeconds, periodInSeconds);
|
||||
((DefaultListModel<Reminder>) reminderApplication.getReminders()).addElement(reminder);
|
||||
});
|
||||
okButton.addActionListener(e -> scheduleReminder(textField, delay, period));
|
||||
}
|
||||
|
||||
private void scheduleReminder(final JTextField textField, final JComboBox<Integer> delay, final JComboBox<Integer> period) {
|
||||
final int periodInSeconds = getTimeInSeconds(period);
|
||||
if (periodInSeconds == 0)
|
||||
scheduleNonRepeatedReminder(textField, delay);
|
||||
else
|
||||
scheduleRepeatedReminder(textField, delay, period);
|
||||
}
|
||||
|
||||
private void scheduleRepeatedReminder(final JTextField textField, final JComboBox<Integer> delay, final JComboBox<Integer> period) {
|
||||
final int delayInSeconds = getTimeInSeconds(delay) + 200;
|
||||
final int periodInSeconds = getTimeInSeconds(period);
|
||||
final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds);
|
||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds), TimeUnit.SECONDS.toMillis(periodInSeconds));
|
||||
}
|
||||
|
||||
private void scheduleNonRepeatedReminder(final JTextField textField, final JComboBox<Integer> delay) {
|
||||
final int delayInSeconds = getTimeInSeconds(delay);
|
||||
final int periodInSeconds = 0;
|
||||
final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds);
|
||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds));
|
||||
|
||||
}
|
||||
|
||||
private int getTimeInSeconds(final JComboBox<Integer> comboBox) {
|
||||
if (comboBox != null && comboBox.getSelectedItem() != null)
|
||||
return ((Integer) comboBox.getSelectedItem());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
private TimerTask getTimerTask(final String reminderText, final Integer delayInSeconds, final Integer periodInSeconds) {
|
||||
return new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
new ReminderPopupFrame(reminderApplication, reminderText, delayInSeconds, periodInSeconds);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private JButton createCancelButton() {
|
||||
final JButton button = new JButton("cancel");
|
||||
button.setName("Cancel");
|
||||
button.addActionListener(e -> this.dispose());
|
||||
return button;
|
||||
}
|
||||
|
||||
private static JLabel createLabel(final String text, final String name) {
|
||||
JLabel label = new JLabel(text);
|
||||
label.setName(name);
|
||||
return label;
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
package reminderapplication;
|
||||
|
||||
import static reminderapplication.ConstraintsBuilder.*;
|
||||
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.HeadlessException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
public class ReminderPopupFrame extends JFrame {
|
||||
|
||||
private static final Timer TIMER = new Timer();
|
||||
private final int AUTOMATIC_CLOSE_TIME_IN_SECONDS = 10;
|
||||
private final TimeReminderApplication reminderApplication;
|
||||
private final JLabel reminderTextLabel;
|
||||
private final JLabel repeatPeriodLabel;
|
||||
private final JLabel setDelayLabel;
|
||||
private final JComboBox<Integer> delay;
|
||||
private final JComboBox<Integer> period;
|
||||
private final JButton cancelButton;
|
||||
private final JButton okButton;
|
||||
private final JTextField textField;
|
||||
private final JLabel delaysLabel;
|
||||
private final JLabel periodLabel;
|
||||
|
||||
public ReminderPopupFrame(TimeReminderApplication reminderApp, final String text, final Integer delayInSeconds, final Integer periodInSeconds) throws HeadlessException {
|
||||
this.reminderApplication = reminderApp;
|
||||
textField = createTextField(text);
|
||||
delay = createDelayComboBox(delayInSeconds);
|
||||
period = createPeriodComboBox(periodInSeconds);
|
||||
cancelButton = createCancelButton();
|
||||
okButton = createDisabledOkButton();
|
||||
reminderTextLabel = createReminderTextLabel();
|
||||
repeatPeriodLabel = createRepeatPeriodLabel();
|
||||
setDelayLabel = createSetDelayLabel();
|
||||
delaysLabel = createDelaysLabel();
|
||||
periodLabel = createPeriodLabel();
|
||||
configureVisualRepresentation();
|
||||
configureActions();
|
||||
}
|
||||
|
||||
private void configureActions() {
|
||||
scheduleClosing();
|
||||
}
|
||||
|
||||
private void scheduleClosing() {
|
||||
final TimerTask timerTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
ReminderPopupFrame.this.dispose();
|
||||
}
|
||||
};
|
||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(AUTOMATIC_CLOSE_TIME_IN_SECONDS));
|
||||
}
|
||||
|
||||
private void configureVisualRepresentation() {
|
||||
configureFrame();
|
||||
setLocationRelativeTo(null);
|
||||
setLayout(new GridBagLayout());
|
||||
add(reminderTextLabel, constraint(0,0));
|
||||
add(repeatPeriodLabel, constraint(1,0));
|
||||
add(setDelayLabel, constraint(2,0));
|
||||
add(textField, constraint(0, 1));
|
||||
add(delay, constraint(1, 1));
|
||||
add(period, constraint(2, 1));
|
||||
add(delaysLabel, constraint(1,3));
|
||||
add(periodLabel, constraint(2,3));
|
||||
add(okButton, constraint(1, 4));
|
||||
add(cancelButton, constraint(2, 4));
|
||||
pack();
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
private void configureFrame() {
|
||||
setTitle("Set Reminder");
|
||||
setName("Set Reminder");
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
}
|
||||
|
||||
private static JLabel createSetDelayLabel() {
|
||||
return createLabel("Set Delay", "Set Delay Label");
|
||||
}
|
||||
|
||||
private static JLabel createRepeatPeriodLabel() {
|
||||
return createLabel("Set Period", "Set Repeat Period Label");
|
||||
}
|
||||
|
||||
private static JLabel createReminderTextLabel() {
|
||||
return createLabel("Reminder Text", "Reminder Text Label");
|
||||
}
|
||||
|
||||
private JLabel createPeriodLabel() {
|
||||
return createLabel("0", "Period label");
|
||||
}
|
||||
|
||||
private JLabel createDelaysLabel() {
|
||||
return createLabel("30", "Delays Label");
|
||||
}
|
||||
|
||||
private JComboBox<Integer> createPeriodComboBox(final Integer periodInSeconds) {
|
||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20}));
|
||||
comboBox.setName("set Period");
|
||||
comboBox.setSelectedItem(periodInSeconds);
|
||||
comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString()));
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private JComboBox<Integer> createDelayComboBox(Integer delay) {
|
||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5}));
|
||||
comboBox.setSelectedItem(delay);
|
||||
comboBox.setName("set Delay");
|
||||
comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString()));
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private JTextField createTextField(final String text) {
|
||||
final JTextField textField = new JTextField(20);
|
||||
textField.setName("Field");
|
||||
textField.setText(text);
|
||||
return textField;
|
||||
}
|
||||
|
||||
private JButton createDisabledOkButton() {
|
||||
final JButton button = new JButton("ok");
|
||||
button.setName("OK");
|
||||
button.setEnabled(false);
|
||||
return button;
|
||||
}
|
||||
|
||||
private JButton createCancelButton() {
|
||||
final JButton button = new JButton("cancel");
|
||||
button.setName("Cancel");
|
||||
button.addActionListener(e -> this.dispose());
|
||||
return button;
|
||||
}
|
||||
|
||||
private static JLabel createLabel(final String text, final String name) {
|
||||
JLabel label = new JLabel(text);
|
||||
label.setName(name);
|
||||
return label;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,3 +7,4 @@
|
||||
- [Random Number Generators in Java 17](https://www.baeldung.com/java-17-random-number-generators)
|
||||
- [Sealed Classes and Interfaces in Java](https://www.baeldung.com/java-sealed-classes-interfaces)
|
||||
- [Migrate From Java 8 to Java 17](https://www.baeldung.com/java-migrate-8-to-17)
|
||||
- [Format Multiple ‘or’ Conditions in an If Statement in Java](https://www.baeldung.com/java-multiple-or-conditions-if-statement)
|
||||
|
||||
1
core-java-modules/core-java-21/README.md
Normal file
1
core-java-modules/core-java-21/README.md
Normal file
@@ -0,0 +1 @@
|
||||
## Relevant Articles
|
||||
34
core-java-modules/core-java-21/pom.xml
Normal file
34
core-java-modules/core-java-21/pom.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>core-java-21</artifactId>
|
||||
<name>core-java-21</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung.core-java-modules</groupId>
|
||||
<artifactId>core-java-modules</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<!-- <build>-->
|
||||
<!-- <plugins>-->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.apache.maven.plugins</groupId>-->
|
||||
<!-- <artifactId>maven-compiler-plugin</artifactId>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <source>{maven.compiler.source.version}</source>-->
|
||||
<!-- <target>{maven.compiler.target.version}</target>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </plugin>-->
|
||||
<!-- </plugins>-->
|
||||
<!-- </build>-->
|
||||
|
||||
<!-- <properties>-->
|
||||
<!-- <maven.compiler.source.version>21</maven.compiler.source.version>-->
|
||||
<!-- <maven.compiler.target.version>21</maven.compiler.target.version>-->
|
||||
<!-- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>-->
|
||||
<!-- </properties>-->
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.sequenced.collections;
|
||||
|
||||
/*
|
||||
interface SequencedCollection<E> extends Collection<E> {
|
||||
// new method
|
||||
SequencedCollection<E> reversed();
|
||||
// methods promoted from Deque
|
||||
void addFirst(E);
|
||||
void addLast(E);
|
||||
E getFirst();
|
||||
E getLast();
|
||||
E removeFirst();
|
||||
E removeLast();
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.baeldung.sequenced.collections;
|
||||
|
||||
/*
|
||||
interface SequencedMap<K,V> extends Map<K,V> {
|
||||
// new methods
|
||||
SequencedMap<K,V> reversed();
|
||||
SequencedSet<K> sequencedKeySet();
|
||||
SequencedCollection<V> sequencedValues();
|
||||
SequencedSet<Entry<K,V>> sequencedEntrySet();
|
||||
V putFirst(K, V);
|
||||
V putLast(K, V);
|
||||
// methods promoted from NavigableMap
|
||||
Entry<K, V> firstEntry();
|
||||
Entry<K, V> lastEntry();
|
||||
Entry<K, V> pollFirstEntry();
|
||||
Entry<K, V> pollLastEntry();
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.baeldung.sequenced.collections;
|
||||
|
||||
/*
|
||||
interface SequencedSet<E> extends Set<E>, SequencedCollection<E> {
|
||||
SequencedSet<E> reversed(); // covariant override
|
||||
}
|
||||
*/
|
||||
@@ -14,3 +14,4 @@ This module contains articles about advanced operations on arrays in Java. They
|
||||
- [Slicing Arrays in Java](https://www.baeldung.com/java-slicing-arrays)
|
||||
- [Combining Two or More Byte Arrays](https://www.baeldung.com/java-concatenate-byte-arrays)
|
||||
- [Calculating the Sum of Two Arrays in Java](https://www.baeldung.com/java-sum-arrays-element-wise)
|
||||
- [Find the Middle Element of an Array in Java](https://www.baeldung.com/java-array-middle-item)
|
||||
|
||||
@@ -12,3 +12,4 @@ This module contains articles about the Java List collection
|
||||
- [Get Unique Values From an ArrayList in Java](https://www.baeldung.com/java-unique-values-arraylist)
|
||||
- [Converting a Java List to a Json Array](https://www.baeldung.com/java-converting-list-to-json-array)
|
||||
- [What’s the Difference Between Iterator and ListIterator?](https://www.baeldung.com/java-iterator-vs-listiterator)
|
||||
- [Create List of Object From Another Type Using Java 8](https://www.baeldung.com/java-generate-list-different-type)
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package com.baeldung.java.streamtoanotherlist;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
class Employee {
|
||||
private final String name;
|
||||
private final Set<String> hobbies = new HashSet<>();
|
||||
private final String email;
|
||||
private String department;
|
||||
|
||||
public Employee(String name, String email, Collection<String> hobbies) {
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
this.hobbies.addAll(hobbies);
|
||||
}
|
||||
}
|
||||
|
||||
class TennisPlayerCandidate {
|
||||
private final String name;
|
||||
private final String email;
|
||||
private final Boolean confirmed = Boolean.FALSE;
|
||||
|
||||
public TennisPlayerCandidate(String name, String email) {
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof TennisPlayerCandidate))
|
||||
return false;
|
||||
|
||||
TennisPlayerCandidate that = (TennisPlayerCandidate) o;
|
||||
|
||||
if (!Objects.equals(name, that.name))
|
||||
return false;
|
||||
return Objects.equals(email, that.email);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = name != null ? name.hashCode() : 0;
|
||||
result = 31 * result + (email != null ? email.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateListOfDifferentTypeUsingStreamUnitTest {
|
||||
private final static List<Employee> EMPLOYEES = Lists.newArrayList(
|
||||
// @formatter:off
|
||||
new Employee("Kai", "kai@company.com", Lists.newArrayList("Football", "Reading", "Chess")),
|
||||
new Employee("Eric", "eric@company.com", Lists.newArrayList("Tennis", "Baseball", "Singing")),
|
||||
new Employee("Saajan", "saajan@company.com", Lists.newArrayList("Tennis", "Baseball", "Singing")),
|
||||
new Employee("Kevin", "kevin@company.com", Lists.newArrayList("Dancing", "Computer Games", "Tennis")),
|
||||
new Employee("Amanda", "amanda@company.com", Lists.newArrayList("Painting", "Yoga", "Dancing"))
|
||||
//@formatter:on
|
||||
);
|
||||
|
||||
private final static List<TennisPlayerCandidate> EXPECTED = Lists.newArrayList(
|
||||
// @formatter:off
|
||||
new TennisPlayerCandidate("Eric", "eric@company.com"),
|
||||
new TennisPlayerCandidate("Saajan", "saajan@company.com"),
|
||||
new TennisPlayerCandidate("Kevin", "kevin@company.com")
|
||||
//@formatter:on
|
||||
);
|
||||
|
||||
@Test
|
||||
void whenUsingStreamForEachFillingAnotherList_thenGetExpectedResult() {
|
||||
List<TennisPlayerCandidate> result = new ArrayList<>();
|
||||
EMPLOYEES.forEach(e -> {
|
||||
if (e.getHobbies()
|
||||
.contains("Tennis")) {
|
||||
result.add(new TennisPlayerCandidate(e.getName(), e.getEmail()));
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(EXPECTED, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingStreamMap_thenGetExpectedResult() {
|
||||
List<TennisPlayerCandidate> result = EMPLOYEES.stream()
|
||||
.filter(e -> e.getHobbies()
|
||||
.contains("Tennis"))
|
||||
.map(e -> new TennisPlayerCandidate(e.getName(), e.getEmail()))
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(EXPECTED, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingCollectorMapping_thenGetExpectedResult() {
|
||||
List<TennisPlayerCandidate> result = EMPLOYEES.stream()
|
||||
.filter(e -> e.getHobbies()
|
||||
.contains("Tennis"))
|
||||
.collect(Collectors.mapping(e -> new TennisPlayerCandidate(e.getName(), e.getEmail()), Collectors.toList()));
|
||||
assertEquals(EXPECTED, result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.baeldung.map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class UsingtoStringUnitTest {
|
||||
|
||||
@Test
|
||||
public void given_HashMapString_whenUsingtoString_thenConvertToHashMapObject() {
|
||||
// Example string representation of a HashMap
|
||||
String hashMapString = "{key1=value1, key2=value2, key3=value3}";
|
||||
|
||||
// Remove unnecessary characters
|
||||
String keyValuePairs = hashMapString.replaceAll("[{}\\s]", "");
|
||||
|
||||
// Split into individual key-value pairs
|
||||
String[] pairs = keyValuePairs.split(",");
|
||||
|
||||
// Create a new HashMap
|
||||
HashMap<String, String> expectedHashMap = new HashMap<>();
|
||||
expectedHashMap.put("key1", "value1");
|
||||
expectedHashMap.put("key2", "value2");
|
||||
expectedHashMap.put("key3", "value3");
|
||||
|
||||
HashMap<String, String> actualHashMap = new HashMap<>();
|
||||
|
||||
// Parse and populate the HashMap
|
||||
for (String pair : pairs) {
|
||||
String[] keyValue = pair.split("=");
|
||||
if (keyValue.length == 2) {
|
||||
actualHashMap.put(keyValue[0], keyValue[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Assert that the converted HashMap matches the expected one
|
||||
assertEquals(expectedHashMap, actualHashMap);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,4 +4,5 @@
|
||||
- [A Guide to LinkedHashSet in Java](https://www.baeldung.com/java-linkedhashset)
|
||||
- [Sorting a HashSet in Java](https://www.baeldung.com/java-sort-hashset)
|
||||
- [How to Get First Item From a Java Set](https://www.baeldung.com/first-item-set)
|
||||
- [Cartesian Product of Any Number of Sets in Java](https://www.baeldung.com/java-cartesian-product-sets)
|
||||
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-set)
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.logging.Logger;
|
||||
|
||||
public class Consumer implements Runnable {
|
||||
private static final Logger log = Logger.getLogger(Consumer.class.getCanonicalName());
|
||||
private boolean running = false;
|
||||
private final DataQueue dataQueue;
|
||||
|
||||
public Consumer(DataQueue dataQueue) {
|
||||
@@ -12,26 +13,36 @@ public class Consumer implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
running = true;
|
||||
consume();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
running = false;
|
||||
}
|
||||
|
||||
public void consume() {
|
||||
while (dataQueue.runFlag) {
|
||||
while (dataQueue.isEmpty() && dataQueue.runFlag) {
|
||||
while (running) {
|
||||
|
||||
if (dataQueue.isEmpty()) {
|
||||
try {
|
||||
dataQueue.waitOnEmpty();
|
||||
dataQueue.waitIsNotEmpty();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
log.severe("Error while waiting to Consume messages.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dataQueue.runFlag) {
|
||||
|
||||
// avoid spurious wake-up
|
||||
if (!running) {
|
||||
break;
|
||||
}
|
||||
Message message = dataQueue.remove();
|
||||
dataQueue.notifyAllForFull();
|
||||
|
||||
Message message = dataQueue.poll();
|
||||
useMessage(message);
|
||||
|
||||
//Sleeping on random time to make it realistic
|
||||
ThreadUtil.sleep((long) (Math.random() * 100));
|
||||
}
|
||||
log.info("Consumer Stopped");
|
||||
}
|
||||
@@ -40,14 +51,7 @@ public class Consumer implements Runnable {
|
||||
if (message != null) {
|
||||
log.info(String.format("[%s] Consuming Message. Id: %d, Data: %f%n",
|
||||
Thread.currentThread().getName(), message.getId(), message.getData()));
|
||||
|
||||
//Sleeping on random time to make it realistic
|
||||
ThreadUtil.sleep((long) (message.getData() * 100));
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
dataQueue.runFlag = false;
|
||||
dataQueue.notifyAllForEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,8 @@ import java.util.Queue;
|
||||
public class DataQueue {
|
||||
private final Queue<Message> queue = new LinkedList<>();
|
||||
private final int maxSize;
|
||||
private final Object FULL_QUEUE = new Object();
|
||||
private final Object EMPTY_QUEUE = new Object();
|
||||
|
||||
public boolean runFlag = true;
|
||||
private final Object IS_NOT_FULL = new Object();
|
||||
private final Object IS_NOT_EMPTY = new Object();
|
||||
|
||||
DataQueue(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
@@ -23,43 +21,42 @@ public class DataQueue {
|
||||
return queue.isEmpty();
|
||||
}
|
||||
|
||||
public void waitOnFull() throws InterruptedException {
|
||||
synchronized (FULL_QUEUE) {
|
||||
FULL_QUEUE.wait();
|
||||
public void waitIsNotFull() throws InterruptedException {
|
||||
synchronized (IS_NOT_FULL) {
|
||||
IS_NOT_FULL.wait();
|
||||
}
|
||||
}
|
||||
|
||||
public void waitOnEmpty() throws InterruptedException {
|
||||
synchronized (EMPTY_QUEUE) {
|
||||
EMPTY_QUEUE.wait();
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyAllForFull() {
|
||||
synchronized (FULL_QUEUE) {
|
||||
FULL_QUEUE.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyAllForEmpty() {
|
||||
synchronized (EMPTY_QUEUE) {
|
||||
EMPTY_QUEUE.notifyAll();
|
||||
public void waitIsNotEmpty() throws InterruptedException {
|
||||
synchronized (IS_NOT_EMPTY) {
|
||||
IS_NOT_EMPTY.wait();
|
||||
}
|
||||
}
|
||||
|
||||
public void add(Message message) {
|
||||
synchronized (queue) {
|
||||
queue.add(message);
|
||||
}
|
||||
queue.add(message);
|
||||
notifyIsNotEmpty();
|
||||
}
|
||||
|
||||
public Message remove() {
|
||||
synchronized (queue) {
|
||||
return queue.poll();
|
||||
}
|
||||
public Message poll() {
|
||||
Message mess = queue.poll();
|
||||
notifyIsNotFull();
|
||||
return mess;
|
||||
}
|
||||
|
||||
public Integer getSize() {
|
||||
return queue.size();
|
||||
}
|
||||
|
||||
private void notifyIsNotFull() {
|
||||
synchronized (IS_NOT_FULL) {
|
||||
IS_NOT_FULL.notify();
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyIsNotEmpty() {
|
||||
synchronized (IS_NOT_EMPTY) {
|
||||
IS_NOT_EMPTY.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package com.baeldung.producerconsumer;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class Producer implements Runnable {
|
||||
private static final Logger log = Logger.getLogger(Producer.class.getCanonicalName());
|
||||
private static final AtomicInteger idSequence = new AtomicInteger(0);
|
||||
private boolean running = false;
|
||||
private final DataQueue dataQueue;
|
||||
private static int idSequence = 0;
|
||||
final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public Producer(DataQueue dataQueue) {
|
||||
this.dataQueue = dataQueue;
|
||||
@@ -15,39 +15,36 @@ public class Producer implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
running = true;
|
||||
produce();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
running = false;
|
||||
}
|
||||
|
||||
public void produce() {
|
||||
while (dataQueue.runFlag) {
|
||||
|
||||
try {
|
||||
lock.lock();
|
||||
while (running) {
|
||||
|
||||
while (dataQueue.isFull() && dataQueue.runFlag) {
|
||||
try {
|
||||
dataQueue.waitOnFull();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dataQueue.runFlag) {
|
||||
if (dataQueue.isFull()) {
|
||||
try {
|
||||
dataQueue.waitIsNotFull();
|
||||
} catch (InterruptedException e) {
|
||||
log.severe("Error while waiting to Produce messages.");
|
||||
break;
|
||||
}
|
||||
|
||||
Message message = generateMessage();
|
||||
dataQueue.add(message);
|
||||
dataQueue.notifyAllForEmpty();
|
||||
|
||||
log.info("Size of the queue is: " + dataQueue.getSize());
|
||||
|
||||
}
|
||||
finally{
|
||||
lock.unlock();
|
||||
|
||||
// avoid spurious wake-up
|
||||
if (!running) {
|
||||
break;
|
||||
}
|
||||
|
||||
dataQueue.add(generateMessage());
|
||||
|
||||
log.info("Size of the queue is: " + dataQueue.getSize());
|
||||
|
||||
//Sleeping on random time to make it realistic
|
||||
ThreadUtil.sleep((long) (Math.random() * 100));
|
||||
}
|
||||
@@ -56,19 +53,11 @@ public class Producer implements Runnable {
|
||||
}
|
||||
|
||||
private Message generateMessage() {
|
||||
Message message = new Message(incrementAndGetId(), Math.random());
|
||||
Message message = new Message(idSequence.incrementAndGet(), Math.random());
|
||||
log.info(String.format("[%s] Generated Message. Id: %d, Data: %f%n",
|
||||
Thread.currentThread().getName(), message.getId(), message.getData()));
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
private static int incrementAndGetId() {
|
||||
return ++idSequence;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
dataQueue.runFlag = false;
|
||||
dataQueue.notifyAllForFull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public class ProducerConsumerDemonstrator {
|
||||
// let threads run for two seconds
|
||||
sleep(2000);
|
||||
|
||||
// Stop threads
|
||||
// stop threads
|
||||
producer.stop();
|
||||
consumer.stop();
|
||||
|
||||
@@ -39,26 +39,31 @@ public class ProducerConsumerDemonstrator {
|
||||
int producerCount = 5;
|
||||
int consumerCount = 5;
|
||||
List<Thread> threads = new ArrayList<>();
|
||||
Producer producer = new Producer(dataQueue);
|
||||
List<Producer> producers = new ArrayList<>();
|
||||
List<Consumer> consumers = new ArrayList<>();
|
||||
|
||||
for(int i = 0; i < producerCount; i++) {
|
||||
Producer producer = new Producer(dataQueue);
|
||||
Thread producerThread = new Thread(producer);
|
||||
producerThread.start();
|
||||
threads.add(producerThread);
|
||||
producers.add(producer);
|
||||
}
|
||||
|
||||
Consumer consumer = new Consumer(dataQueue);
|
||||
for(int i = 0; i < consumerCount; i++) {
|
||||
Consumer consumer = new Consumer(dataQueue);
|
||||
Thread consumerThread = new Thread(consumer);
|
||||
consumerThread.start();
|
||||
threads.add(consumerThread);
|
||||
consumers.add(consumer);
|
||||
}
|
||||
|
||||
// let threads run for ten seconds
|
||||
sleep(10000);
|
||||
|
||||
// Stop threads
|
||||
producer.stop();
|
||||
consumer.stop();
|
||||
// stop threads
|
||||
consumers.forEach(Consumer::stop);
|
||||
producers.forEach(Producer::stop);
|
||||
|
||||
waitForAllThreadsToComplete(threads);
|
||||
}
|
||||
|
||||
@@ -10,4 +10,5 @@ This module contains articles about date operations in Java.
|
||||
- [How to Get Last Day of a Month in Java](https://www.baeldung.com/java-last-day-month)
|
||||
- [Getting Yesterday’s Date in Java](https://www.baeldung.com/java-find-yesterdays-date)
|
||||
- [How to Get the Start and End Dates of a Year Using Java](https://www.baeldung.com/java-date-year-start-end)
|
||||
- [Convert Between Java LocalDate and Epoch](https://www.baeldung.com/java-localdate-epoch)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-date-operations-2)
|
||||
|
||||
@@ -43,6 +43,17 @@
|
||||
<version>${angus-activation.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jodd</groupId>
|
||||
<artifactId>jodd-util</artifactId>
|
||||
<version>${jodd-util.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.j256.simplemagic</groupId>
|
||||
<artifactId>simplemagic</artifactId>
|
||||
<version>${simplemagic.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -54,6 +65,13 @@
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>11</source>
|
||||
<target>11</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
@@ -135,6 +153,8 @@
|
||||
<fscontext.version>4.4.2</fscontext.version>
|
||||
<jakarta-activation-api.version>2.1.2</jakarta-activation-api.version>
|
||||
<angus-activation.version>2.0.1</angus-activation.version>
|
||||
<jodd-util.version>6.2.1</jodd-util.version>
|
||||
<simplemagic.version>1.17</simplemagic.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.baeldung.close;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.io.input.AutoCloseInputStream;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StreamCloseUnitTest {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(StreamCloseUnitTest.class);
|
||||
|
||||
@Mock
|
||||
private OutputStream wrappedOutputStream;
|
||||
|
||||
@Mock
|
||||
private InputStream wrappedInputStream;
|
||||
|
||||
@Test
|
||||
public void whenStreamClosedByFinally_thenIOStreamsCloseCalled() throws IOException {
|
||||
|
||||
InputStream inputStream = null;
|
||||
OutputStream outputStream = null;
|
||||
|
||||
try {
|
||||
inputStream = new BufferedInputStream(wrappedInputStream);
|
||||
outputStream = new BufferedOutputStream(wrappedOutputStream);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
if (inputStream != null)
|
||||
inputStream.close();
|
||||
}
|
||||
catch (IOException ioe1) {
|
||||
log.error("Cannot close InputStream");
|
||||
}
|
||||
try {
|
||||
if (outputStream != null)
|
||||
outputStream.close();
|
||||
}
|
||||
catch (IOException ioe2) {
|
||||
log.error("Cannot close OutputStream");
|
||||
}
|
||||
}
|
||||
|
||||
verify(wrappedInputStream).close();
|
||||
verify(wrappedOutputStream).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenStreamClosedByCloseQuietly_thenIOStreamsCloseCalled() throws IOException {
|
||||
|
||||
InputStream inputStream = null;
|
||||
OutputStream outputStream = null;
|
||||
|
||||
try {
|
||||
inputStream = new BufferedInputStream(wrappedInputStream);
|
||||
outputStream = new BufferedOutputStream(wrappedOutputStream);
|
||||
}
|
||||
finally {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
IOUtils.closeQuietly(outputStream);
|
||||
}
|
||||
|
||||
verify(wrappedInputStream).close();
|
||||
verify(wrappedOutputStream).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenFinishReadOnAutoCloseInputStream_thenInputStreamsCloseCalled() throws IOException {
|
||||
|
||||
// Mimic no more data in the InputStream
|
||||
when(wrappedInputStream.read(any(byte[].class))).thenReturn(-1);
|
||||
|
||||
InputStream inputStream = AutoCloseInputStream.builder().setInputStream(wrappedInputStream).get();
|
||||
|
||||
byte[] buffer = new byte[256];
|
||||
while (inputStream.read(buffer) != -1) {
|
||||
}
|
||||
|
||||
verify(wrappedInputStream).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenStreamClosedByWithResources_thenIOStreamsCloseCalled() throws IOException {
|
||||
|
||||
try (BufferedInputStream inputStream = new BufferedInputStream(wrappedInputStream);
|
||||
BufferedOutputStream outputStream = new BufferedOutputStream(wrappedOutputStream)) {
|
||||
}
|
||||
|
||||
verify(wrappedInputStream).close();
|
||||
verify(wrappedOutputStream).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenStreamClosedByWithResourcesJava9_thenIOStreamsCloseCalled() throws IOException {
|
||||
|
||||
InputStream inputStream = new BufferedInputStream(wrappedInputStream);
|
||||
OutputStream outputStream = new BufferedOutputStream(wrappedOutputStream);
|
||||
|
||||
try (inputStream; outputStream) {
|
||||
}
|
||||
|
||||
verify(wrappedInputStream).close();
|
||||
verify(wrappedOutputStream).close();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.baeldung.extension;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.tika.mime.MimeTypeException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.j256.simplemagic.ContentInfo;
|
||||
|
||||
public class ExtensionFromMimeTypeUnitTest {
|
||||
private static final String IMAGE_JPEG_MIME_TYPE = "image/jpeg";
|
||||
@Test
|
||||
public void whenUsingTika_thenGetFileExtension() throws MimeTypeException {
|
||||
List<String> expectedExtensions = Arrays.asList(".jpg", ".jpeg", ".jpe", ".jif", ".jfif", ".jfi");
|
||||
org.apache.tika.mime.MimeTypes allTypes = org.apache.tika.mime.MimeTypes.getDefaultMimeTypes();
|
||||
org.apache.tika.mime.MimeType type = allTypes.forName(IMAGE_JPEG_MIME_TYPE);
|
||||
String primaryExtension = type.getExtension();
|
||||
assertEquals(".jpg", primaryExtension);
|
||||
List<String> detectedExtensions = type.getExtensions();
|
||||
assertThat(detectedExtensions).containsExactlyElementsOf(expectedExtensions);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingJodd_thenGetFileExtension() {
|
||||
List<String> expectedExtensions = Arrays.asList("jpeg", "jpg", "jpe");
|
||||
String[] detectedExtensions = jodd.net.MimeTypes.findExtensionsByMimeTypes(IMAGE_JPEG_MIME_TYPE, false);
|
||||
assertThat(detectedExtensions).containsExactlyElementsOf(expectedExtensions);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingMimetypesFileTypeMap_thenGetFileExtension() {
|
||||
List<String> expectedExtensions = Arrays.asList("jpeg", "jpg", "jpe");
|
||||
ContentInfo contentInfo = new ContentInfo("", IMAGE_JPEG_MIME_TYPE, "", true);
|
||||
String[] detectedExtensions = contentInfo.getFileExtensions();
|
||||
assertThat(detectedExtensions).containsExactlyElementsOf(expectedExtensions);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingCustomLogic_thenGetFileExtension() {
|
||||
Map<String, Set<String>> mimeExtensionsMap = new HashMap<>();
|
||||
List<String> expectedExtensions = Arrays.asList(".jpg", ".jpe", ".jpeg");
|
||||
addMimeExtensions(mimeExtensionsMap, "image/jpeg", ".jpg");
|
||||
addMimeExtensions(mimeExtensionsMap, "image/jpeg", ".jpe");
|
||||
addMimeExtensions(mimeExtensionsMap, "image/jpeg", ".jpeg");
|
||||
|
||||
Set<String> detectedExtensions = mimeExtensionsMap.get(IMAGE_JPEG_MIME_TYPE);
|
||||
assertThat(detectedExtensions).containsExactlyElementsOf(expectedExtensions);
|
||||
}
|
||||
|
||||
private void addMimeExtensions(Map<String, Set<String>> map, String mimeType, String extension) {
|
||||
map.computeIfAbsent(mimeType, k -> new HashSet<>()).add(extension);
|
||||
}
|
||||
}
|
||||
@@ -6,3 +6,5 @@ This module contains articles about core features in the Java language
|
||||
|
||||
- [Convert One Enum to Another Enum in Java](https://www.baeldung.com/java-convert-enums)
|
||||
- [What Is the Maximum Depth of the Java Call Stack?](https://www.baeldung.com/java-call-stack-max-depth)
|
||||
- [Get a Random Element From a Set in Java](https://www.baeldung.com/java-set-draw-sample)
|
||||
- [Stop Executing Further Code in Java](https://www.baeldung.com/java-stop-running-code)
|
||||
|
||||
@@ -11,4 +11,5 @@
|
||||
- [Java Program to Calculate the Standard Deviation](https://www.baeldung.com/java-calculate-standard-deviation)
|
||||
- [Java Program to Print Pascal’s Triangle](https://www.baeldung.com/java-pascal-triangle)
|
||||
- [Java Money and the Currency API](http://www.baeldung.com/java-money-and-currency)
|
||||
- [Clamp Function in Java](https://www.baeldung.com/java-clamp-function)
|
||||
- More articles: [[<-- Prev]](/core-java-modules/core-java-lang-math-2)
|
||||
|
||||
@@ -33,7 +33,7 @@ public class ClampFunctionUnitTest {
|
||||
* This method uses the clamp() method introduced in Java 21
|
||||
@Test
|
||||
public void givenValueWithinRange_whenClamp_thenReturnValue() {
|
||||
assertEquals(20, Math.clamp(20, 67,98));
|
||||
assertEquals(20, Math.clamp(20, 17, 98));
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
@@ -8,3 +8,4 @@ This module contains articles about Object Oriented Programming (OOP) in Java
|
||||
- [Pass-By-Value as a Parameter Passing Mechanism in Java](https://www.baeldung.com/java-pass-by-value-or-pass-by-reference)
|
||||
- [Check If All the Variables of an Object Are Null](https://www.baeldung.com/java-check-all-variables-object-null)
|
||||
- [Law of Demeter in Java](https://www.baeldung.com/java-demeter-law)
|
||||
- [Java Interface Naming Conventions](https://www.baeldung.com/java-interface-naming-conventions)
|
||||
|
||||
@@ -9,3 +9,4 @@ This module contains articles about Java operators
|
||||
- [Getting a Bit at a Certain Position from Integral Values](https://www.baeldung.com/java-get-bit-at-position)
|
||||
- [Check if at Least Two Out of Three Booleans Are True in Java](https://www.baeldung.com/java-check-two-of-three-booleans)
|
||||
- [Alternatives for instanceof Operator in Java](https://www.baeldung.com/java-instanceof-alternatives)
|
||||
- [What Does “––>” Mean in Java?](https://www.baeldung.com/java-minus-minus-greaterthan)
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.baeldung.doubleminusgreaterthan;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
public class DoubleMinusAndGreaterThanUnitTest {
|
||||
|
||||
@Test
|
||||
void whenUsingDoubleMinusAndGreaterThan_thenGetTheExpectedResult() {
|
||||
List<Integer> resultWhile = new ArrayList<>();
|
||||
int i = 6;
|
||||
while (i-- > 0) {
|
||||
resultWhile.add(i);
|
||||
}
|
||||
assertEquals(Lists.newArrayList(5, 4, 3, 2, 1, 0), resultWhile);
|
||||
|
||||
List<Integer> resultFor = new ArrayList<>();
|
||||
for (int j = 6; j-- > 0; ) {
|
||||
resultFor.add(j);
|
||||
}
|
||||
|
||||
assertEquals(Lists.newArrayList(5, 4, 3, 2, 1, 0), resultFor);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingOtherOperatorsSimilarly_thenGetTheExpectedResult() {
|
||||
// <++
|
||||
List<Integer> result = new ArrayList<>();
|
||||
int i = -1;
|
||||
while (i++ < 5) {
|
||||
result.add(i);
|
||||
}
|
||||
assertEquals(Lists.newArrayList(0, 1, 2, 3, 4, 5), result);
|
||||
|
||||
// <--
|
||||
result.clear();
|
||||
int j = 10;
|
||||
while (0 < --j) {
|
||||
result.add(j);
|
||||
}
|
||||
assertEquals(Lists.newArrayList(9, 8, 7, 6, 5, 4, 3, 2, 1), result);
|
||||
|
||||
// >++
|
||||
result.clear();
|
||||
int n = 0;
|
||||
while (6 > ++n) {
|
||||
result.add(n);
|
||||
}
|
||||
assertEquals(Lists.newArrayList(1, 2, 3, 4, 5), result);
|
||||
|
||||
// >>>=
|
||||
result.clear();
|
||||
int x = 32;
|
||||
while ((x >>>= 1) > 1) {
|
||||
result.add(x);
|
||||
}
|
||||
assertEquals(Lists.newArrayList(16, 8, 4, 2), result);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
### Relevant Articles:
|
||||
- [Convert a Number to a Letter in Java](https://www.baeldung.com/java-convert-number-to-letter)
|
||||
- [Convert Long to BigDecimal in Java](https://www.baeldung.com/java-convert-long-bigdecimal)
|
||||
- [Convert int to Long in Java](https://www.baeldung.com/java-convert-int-long)
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.baeldung.reflection;
|
||||
|
||||
public class Employee extends Person {
|
||||
|
||||
public static final String LABEL = "employee";
|
||||
public int employeeId;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.baeldung.reflection;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
@@ -9,128 +10,170 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
public class PersonAndEmployeeReflectionUnitTest {
|
||||
|
||||
// Fields names
|
||||
private static final String LAST_NAME_FIELD = "lastName";
|
||||
private static final String FIRST_NAME_FIELD = "firstName";
|
||||
private static final String EMPLOYEE_ID_FIELD = "employeeId";
|
||||
private static final String EMPLOYEE_TYPE_FIELD = "LABEL";
|
||||
private static final String MONTH_EMPLOYEE_REWARD_FIELD = "reward";
|
||||
|
||||
@Test
|
||||
public void givenPersonClass_whenGetDeclaredFields_thenTwoFields() {
|
||||
// When
|
||||
Field[] allFields = Person.class.getDeclaredFields();
|
||||
List<Field> allFields = Arrays.asList(Person.class.getDeclaredFields());
|
||||
|
||||
// Then
|
||||
assertEquals(2, allFields.length);
|
||||
|
||||
assertTrue(Arrays.stream(allFields).anyMatch(field ->
|
||||
field.getName().equals(LAST_NAME_FIELD)
|
||||
&& field.getType().equals(String.class))
|
||||
);
|
||||
assertTrue(Arrays.stream(allFields).anyMatch(field ->
|
||||
field.getName().equals(FIRST_NAME_FIELD)
|
||||
&& field.getType().equals(String.class))
|
||||
);
|
||||
assertEquals(2, allFields.size());
|
||||
Field lastName = allFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(LAST_NAME_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"));
|
||||
assertEquals(String.class, lastName.getType());
|
||||
Field firstName = allFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(FIRST_NAME_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"));
|
||||
assertEquals(String.class, firstName.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenEmployeeClass_whenGetDeclaredFields_thenOneField() {
|
||||
// When
|
||||
Field[] allFields = Employee.class.getDeclaredFields();
|
||||
public void givenEmployeeClass_whenGetDeclaredFields_thenFilterAndReturnStaticField() {
|
||||
List<Field> publicStaticField = Arrays.stream(Employee.class.getDeclaredFields())
|
||||
.filter(field -> Modifier.isStatic(field.getModifiers()) && Modifier.isPublic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// Then
|
||||
assertEquals(1, allFields.length);
|
||||
|
||||
assertTrue(Arrays.stream(allFields).anyMatch(field ->
|
||||
field.getName().equals(EMPLOYEE_ID_FIELD)
|
||||
&& field.getType().equals(int.class))
|
||||
);
|
||||
assertEquals(1, publicStaticField.size());
|
||||
Field employeeTypeField = publicStaticField.get(0);
|
||||
assertEquals(EMPLOYEE_TYPE_FIELD, employeeTypeField.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenEmployeeClass_whenSuperClassGetDeclaredFields_thenOneField() {
|
||||
// When
|
||||
Field[] allFields = Employee.class.getSuperclass().getDeclaredFields();
|
||||
public void givenEmployeeClass_whenGetDeclaredFields_thenTwoField() {
|
||||
List<Field> allFields = Arrays.asList(Employee.class.getDeclaredFields());
|
||||
|
||||
// Then
|
||||
assertEquals(2, allFields.length);
|
||||
|
||||
assertTrue(Arrays.stream(allFields).anyMatch(field ->
|
||||
field.getName().equals(LAST_NAME_FIELD)
|
||||
&& field.getType().equals(String.class))
|
||||
);
|
||||
assertTrue(Arrays.stream(allFields).anyMatch(field ->
|
||||
field.getName().equals(FIRST_NAME_FIELD)
|
||||
&& field.getType().equals(String.class))
|
||||
);
|
||||
assertEquals(2, allFields.size());
|
||||
Field employeeIdField = allFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(EMPLOYEE_ID_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"));
|
||||
assertEquals(int.class, employeeIdField.getType());
|
||||
Field employeeTypeField = allFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(EMPLOYEE_TYPE_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"));
|
||||
assertEquals(String.class, employeeTypeField.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenEmployeeClass_whenGetDeclaredFieldsOnBothClasses_thenThreeFields() {
|
||||
// When
|
||||
Field[] personFields = Employee.class.getSuperclass().getDeclaredFields();
|
||||
Field[] employeeFields = Employee.class.getDeclaredFields();
|
||||
Field[] allFields = new Field[employeeFields.length + personFields.length];
|
||||
Arrays.setAll(allFields, i -> (i < personFields.length ? personFields[i] : employeeFields[i - personFields.length]));
|
||||
public void givenEmployeeClass_whenSuperClassGetDeclaredFields_thenTwoField() {
|
||||
List<Field> allFields = Arrays.asList(Employee.class.getSuperclass()
|
||||
.getDeclaredFields());
|
||||
|
||||
// Then
|
||||
assertEquals(3, allFields.length);
|
||||
assertEquals(2, allFields.size());
|
||||
Field lastNameField = allFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(LAST_NAME_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"));
|
||||
assertEquals(String.class, lastNameField.getType());
|
||||
Field firstNameField = allFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(FIRST_NAME_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"));
|
||||
assertEquals(String.class, firstNameField.getType());
|
||||
}
|
||||
|
||||
assertTrue(Arrays.stream(allFields).anyMatch(field ->
|
||||
field.getName().equals(LAST_NAME_FIELD)
|
||||
&& field.getType().equals(String.class))
|
||||
);
|
||||
assertTrue(Arrays.stream(allFields).anyMatch(field ->
|
||||
field.getName().equals(FIRST_NAME_FIELD)
|
||||
&& field.getType().equals(String.class))
|
||||
);
|
||||
assertTrue(Arrays.stream(allFields).anyMatch(field ->
|
||||
field.getName().equals(EMPLOYEE_ID_FIELD)
|
||||
&& field.getType().equals(int.class))
|
||||
);
|
||||
@Test
|
||||
public void givenEmployeeClass_whenGetDeclaredFieldsOnBothClasses_thenFourFields() {
|
||||
List<Field> personFields = Arrays.asList(Employee.class.getSuperclass()
|
||||
.getDeclaredFields());
|
||||
List<Field> employeeFields = Arrays.asList(Employee.class.getDeclaredFields());
|
||||
List<Field> allFields = Stream.concat(personFields.stream(), employeeFields.stream())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
assertEquals(4, allFields.size());
|
||||
Field lastNameField = allFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(LAST_NAME_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"));
|
||||
assertEquals(String.class, lastNameField.getType());
|
||||
Field firstNameField = allFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(FIRST_NAME_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"));
|
||||
assertEquals(String.class, firstNameField.getType());
|
||||
Field employeeIdField = allFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(EMPLOYEE_ID_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"));
|
||||
assertEquals(int.class, employeeIdField.getType());
|
||||
Field employeeTypeField = allFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(EMPLOYEE_TYPE_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"));
|
||||
assertEquals(String.class, employeeTypeField.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenEmployeeClass_whenGetDeclaredFieldsOnEmployeeSuperclassWithModifiersFilter_thenOneFields() {
|
||||
// When
|
||||
List<Field> personFields = Arrays.stream(Employee.class.getSuperclass().getDeclaredFields())
|
||||
.filter(f -> Modifier.isPublic(f.getModifiers()) || Modifier.isProtected(f.getModifiers()))
|
||||
.collect(Collectors.toList());
|
||||
List<Field> personFields = Arrays.stream(Employee.class.getSuperclass()
|
||||
.getDeclaredFields())
|
||||
.filter(f -> Modifier.isPublic(f.getModifiers()) || Modifier.isProtected(f.getModifiers()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// Then
|
||||
assertEquals(1, personFields.size());
|
||||
|
||||
assertTrue(personFields.stream().anyMatch(field ->
|
||||
field.getName().equals(LAST_NAME_FIELD)
|
||||
&& field.getType().equals(String.class))
|
||||
);
|
||||
Field personField = personFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(LAST_NAME_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"));
|
||||
assertEquals(String.class, personField.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMonthEmployeeClass_whenGetAllFields_thenThreeFields() {
|
||||
// When
|
||||
public void givenMonthEmployeeClass_whenGetAllFields_thenFourFields() {
|
||||
List<Field> allFields = getAllFields(MonthEmployee.class);
|
||||
|
||||
// Then
|
||||
assertEquals(3, allFields.size());
|
||||
|
||||
assertTrue(allFields.stream().anyMatch(field ->
|
||||
field.getName().equals(LAST_NAME_FIELD)
|
||||
&& field.getType().equals(String.class))
|
||||
);
|
||||
assertTrue(allFields.stream().anyMatch(field ->
|
||||
field.getName().equals(EMPLOYEE_ID_FIELD)
|
||||
&& field.getType().equals(int.class))
|
||||
);
|
||||
assertTrue(allFields.stream().anyMatch(field ->
|
||||
field.getName().equals(MONTH_EMPLOYEE_REWARD_FIELD)
|
||||
&& field.getType().equals(double.class))
|
||||
);
|
||||
assertEquals(4, allFields.size());
|
||||
assertFalse(allFields.stream()
|
||||
.anyMatch(field -> field.getName()
|
||||
.equals(FIRST_NAME_FIELD)));
|
||||
assertEquals(String.class, allFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(LAST_NAME_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"))
|
||||
.getType());
|
||||
assertEquals(int.class, allFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(EMPLOYEE_ID_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"))
|
||||
.getType());
|
||||
assertEquals(double.class, allFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(MONTH_EMPLOYEE_REWARD_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"))
|
||||
.getType());
|
||||
assertEquals(String.class, allFields.stream()
|
||||
.filter(field -> field.getName()
|
||||
.equals(EMPLOYEE_TYPE_FIELD))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Field not found"))
|
||||
.getType());
|
||||
}
|
||||
|
||||
public List<Field> getAllFields(Class clazz) {
|
||||
@@ -140,8 +183,8 @@ public class PersonAndEmployeeReflectionUnitTest {
|
||||
|
||||
List<Field> result = new ArrayList<>(getAllFields(clazz.getSuperclass()));
|
||||
List<Field> filteredFields = Arrays.stream(clazz.getDeclaredFields())
|
||||
.filter(f -> Modifier.isPublic(f.getModifiers()) || Modifier.isProtected(f.getModifiers()))
|
||||
.collect(Collectors.toList());
|
||||
.filter(f -> Modifier.isPublic(f.getModifiers()) || Modifier.isProtected(f.getModifiers()))
|
||||
.collect(Collectors.toList());
|
||||
result.addAll(filteredFields);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -7,4 +7,6 @@
|
||||
- [Creating a Java Array from Regular Expression Matches](https://www.baeldung.com/java-array-regex-matches)
|
||||
- [Getting the Text That Follows After the Regex Match in Java](https://www.baeldung.com/java-regex-text-after-match)
|
||||
- [Regular Expression: \z vs \Z Anchors in Java](https://www.baeldung.com/java-regular-expression-z-vs-z-anchors)
|
||||
- [Extract Text Between Square Brackets](https://www.baeldung.com/java-get-content-between-square-brackets)
|
||||
- [Get the Indexes of Regex Pattern Matches in Java](https://www.baeldung.com/java-indexes-regex-pattern-matches)
|
||||
- More articles: [[<-- prev]](/core-java-modules/core-java-regex)
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
This module contains articles about core Java Security
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
- [Check if Certificate Is Self-Signed or CA-Signed With Java](https://www.baeldung.com/java-check-certificate-sign)
|
||||
- More articles: [[<-- prev]](/core-java-modules/core-java-security-3)
|
||||
|
||||
@@ -13,4 +13,22 @@
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
<version>${bouncycastle.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cryptacular</groupId>
|
||||
<artifactId>cryptacular</artifactId>
|
||||
<version>${cryptacular.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<bouncycastle.version>1.70</bouncycastle.version>
|
||||
<cryptacular.version>1.2.6</cryptacular.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,20 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDPjCCAiagAwIBAgIJAPvd1gx14C3CMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV
|
||||
BAYTAk1BMRAwDgYDVQQIEwdNb3JvY2NvMRMwEQYDVQQHEwpDYXNhYmxhbmNhMREw
|
||||
DwYDVQQDEwhCYWVsZHVuZzAeFw0xNzEwMTIxMDQzMTRaFw0yNzEwMTMxMDQzMTRa
|
||||
MEcxCzAJBgNVBAYTAk1BMRAwDgYDVQQIEwdNb3JvY2NvMRMwEQYDVQQHEwpDYXNh
|
||||
YmxhbmNhMREwDwYDVQQDEwhCYWVsZHVuZzCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||
ADCCAQoCggEBAMyi5GmOeN4QaH/CP5gSOyHX8znb5TDHWV8wc+ZT7kNU8zt5tGMh
|
||||
jozK6hax155/6tOsBDR0rSYBhL+Dm/+uCVS7qOlRHhf6cNGtzGF1gnNJB2WjI8oM
|
||||
AYm24xpLj1WphKUwKrn3nTMPnQup5OoNAMYl99flANrRYVjjxrLQvDZDUio6Iujr
|
||||
CZ2TtXGM0g/gP++28KT7g1KlUui3xtB0u33wx7UN8Fix3JmjOaPHGwxGpwP3VGSj
|
||||
fs8cuhqVwRQaZpCOoHU/P8wpXKw80sSdhz+SRueMPtVYqK0CiLL5/O0h0Y3le4IV
|
||||
whgg3KG1iTGOWn60UMFn1EYmQ18k5Nsma6UCAwEAAaMtMCswCQYDVR0TBAIwADAR
|
||||
BglghkgBhvhCAQEEBAMCBPAwCwYDVR0PBAQDAgUgMA0GCSqGSIb3DQEBBQUAA4IB
|
||||
AQC8DDBmJ3p4xytxBiE0s4p1715WT6Dm/QJHp0XC0hkSoyZKDh+XVmrzm+J3SiW1
|
||||
vpswb5hLgPo040YX9jnDmgOD+TpleTuKHxZRYj92UYWmdjkWLVtFMcvOh+gxBiAP
|
||||
pHIqZsqo8lfcyAuh8Jx834IXbknfCUtERDLG/rU9P/3XJhrM2GC5qPQznrW4EYhU
|
||||
CGPyIJXmvATMVvXMWCtfogAL+n42vjYXQXZoAWomHhLHoNbSJUErnNdWDOh4WoJt
|
||||
XJCxA6U5LSBplqb3wB2hUTqw+0admKltvmy+KA1PD7OxoGiY7V544zeGqJam1qxU
|
||||
ia7y5BL6uOa/4ShSV8pcJDYz
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.baeldung.certificate;
|
||||
|
||||
import org.bouncycastle.asn1.x500.RDN;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.asn1.x500.style.BCStyle;
|
||||
import org.bouncycastle.asn1.x500.style.IETFUtils;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.cryptacular.util.CertUtil;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.naming.ldap.LdapName;
|
||||
import javax.naming.ldap.Rdn;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
import java.io.FileInputStream;
|
||||
import java.security.Security;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class ExtractCommonNameUnitTest {
|
||||
|
||||
private static final String EXPECTED_CN = "Baeldung";
|
||||
|
||||
private String certificatePath = "src/main/resources/Baeldung.cer";
|
||||
|
||||
private X509Certificate certificate;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", "BC");
|
||||
certificate = (X509Certificate) certificateFactory.generateCertificate(new FileInputStream(certificatePath));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingBouncyCastle_thenExtractCommonName() {
|
||||
X500Principal principal = certificate.getSubjectX500Principal();
|
||||
X500Name x500Name = new X500Name(principal.getName());
|
||||
RDN[] rdns = x500Name.getRDNs(BCStyle.CN);
|
||||
List<String> names = new ArrayList<>();
|
||||
for (RDN rdn : rdns) {
|
||||
String name = IETFUtils.valueToString(rdn.getFirst().getValue());
|
||||
names.add(name);
|
||||
}
|
||||
|
||||
for (String commonName : names) {
|
||||
assertEquals(EXPECTED_CN, commonName);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingLDAPAPI_thenExtractCommonName() throws Exception {
|
||||
X500Principal principal = certificate.getSubjectX500Principal();
|
||||
LdapName ldapDN = new LdapName(principal.getName());
|
||||
List<String> names = new ArrayList<>();
|
||||
for (Rdn rdn : ldapDN.getRdns()) {
|
||||
if (rdn.getType().equalsIgnoreCase("cn")) {
|
||||
String name = rdn.getValue().toString();
|
||||
names.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
for (String commonName : names) {
|
||||
assertEquals(EXPECTED_CN, commonName);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingCryptacular_thenExtractCommonName() {
|
||||
String commonName = CertUtil.subjectCN(certificate);
|
||||
assertEquals(EXPECTED_CN, commonName);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingRegex_thenExtractCommonName() {
|
||||
X500Principal principal = certificate.getSubjectX500Principal();
|
||||
List<String> names = new ArrayList<>();
|
||||
Pattern pattern = Pattern.compile("CN=([^,]+)");
|
||||
Matcher matcher = pattern.matcher(principal.getName());
|
||||
while (matcher.find()) {
|
||||
names.add(matcher.group(1));
|
||||
}
|
||||
|
||||
for (String commonName : names) {
|
||||
assertEquals(EXPECTED_CN, commonName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
## Relevant Articles
|
||||
- [Difference Between parallelStream() and stream().parallel() in Java](https://www.baeldung.com/java-parallelstream-vs-stream-parallel)
|
||||
- [Working With Empty Stream in Java](https://www.baeldung.com/java-empty-stream)
|
||||
- [Aggregate Runtime Exceptions in Java Streams](https://www.baeldung.com/java-streams-aggregate-exceptions)
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.baeldung.streams.streamsvsloops;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Level;
|
||||
import org.openjdk.jmh.annotations.Measurement;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.Setup;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.Warmup;
|
||||
import org.openjdk.jmh.runner.Runner;
|
||||
import org.openjdk.jmh.runner.RunnerException;
|
||||
import org.openjdk.jmh.runner.options.Options;
|
||||
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS)
|
||||
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
|
||||
@Fork(1)
|
||||
public class PerformanceBenchmark {
|
||||
|
||||
@State(Scope.Thread)
|
||||
public static class MyState {
|
||||
List<Integer> numbers;
|
||||
|
||||
@Setup(Level.Trial)
|
||||
public void setUp() {
|
||||
numbers = new ArrayList<>();
|
||||
for (int i = 0; i < 1_000_000; i++) {
|
||||
numbers.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int forLoopBenchmark(MyState state) {
|
||||
int sum = 0;
|
||||
for (int number : state.numbers) {
|
||||
if (number % 2 == 0) {
|
||||
sum = sum + (number * number);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int parallelStreamBenchMark(MyState state) {
|
||||
return state.numbers.parallelStream()
|
||||
.filter(number -> number % 2 == 0)
|
||||
.map(number -> number * number)
|
||||
.reduce(0, Integer::sum);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int concurrentForLoopBenchmark(MyState state) throws InterruptedException, ExecutionException {
|
||||
int numThreads = Runtime.getRuntime().availableProcessors();
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(numThreads);
|
||||
List<Callable<Integer>> tasks = new ArrayList<>();
|
||||
int chunkSize = state.numbers.size() / numThreads;
|
||||
|
||||
for (int i = 0; i < numThreads; i++) {
|
||||
final int start = i * chunkSize;
|
||||
final int end = (i == numThreads - 1) ? state.numbers.size() : (i + 1) * chunkSize;
|
||||
tasks.add(() -> {
|
||||
int sum = 0;
|
||||
for (int j = start; j < end; j++) {
|
||||
int number = state.numbers.get(j);
|
||||
if (number % 2 == 0) {
|
||||
sum = sum + (number * number);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
});
|
||||
}
|
||||
|
||||
int totalSum = 0;
|
||||
for (Future<Integer> result : executorService.invokeAll(tasks)) {
|
||||
totalSum += result.get();
|
||||
}
|
||||
|
||||
executorService.shutdown();
|
||||
return totalSum;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int streamBenchMark(MyState state) {
|
||||
return state.numbers.stream()
|
||||
.filter(number -> number % 2 == 0)
|
||||
.map(number -> number * number)
|
||||
.reduce(0, Integer::sum);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws RunnerException {
|
||||
Options options = new OptionsBuilder().include(PerformanceBenchmark.class.getSimpleName())
|
||||
.build();
|
||||
new Runner(options).run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.baeldung.streamsvsloops;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class StreamsVsLoopsUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenListWithFruits_whenFilterUsingStream_thenReturnedCount() {
|
||||
List<String> fruits = Arrays.asList("apple", "banana", "orange", "grape");
|
||||
long count = fruits.stream()
|
||||
.filter(fruit -> fruit.length() > 5)
|
||||
.count();
|
||||
assertEquals(2, count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenListWithFruits_whenFilterUsingForLoop_thenReturnedCount() {
|
||||
List<String> fruits = Arrays.asList("apple", "banana", "orange", "grape");
|
||||
long count = 0; for (String fruit : fruits) {
|
||||
if (fruit.length() > 5) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
assertEquals(2, count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenListWithFruits_whenApplyUppercase_thenNewListGenerated() {
|
||||
List<String> desiredArray = new ArrayList<>(Arrays.asList("APPLE", "BANANA", "ORANGE"));
|
||||
List<String> fruits = new ArrayList<>(Arrays.asList("apple", "banana", "orange"));
|
||||
List<String> upperCaseFruits = fruits.stream()
|
||||
.map(fruit -> fruit.toUpperCase())
|
||||
.collect(Collectors.toList());
|
||||
assertThat(desiredArray, is(upperCaseFruits));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenListWithFruits_whenApplyUppercase_elementsAreUpdated() {
|
||||
List<String> desiredArray = new ArrayList<>(Arrays.asList("APPLE", "BANANA", "ORANGE"));
|
||||
List<String> fruits = new ArrayList<>(Arrays.asList("apple", "banana", "orange"));
|
||||
for (int i = 0; i < fruits.size(); i++) {
|
||||
fruits.set(i, fruits.get(i).toUpperCase());
|
||||
}
|
||||
assertThat(desiredArray, is(fruits));
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ public class StringTooLongUnitTest {
|
||||
@Test
|
||||
public void whenStoringInPropertiesString_thenNoCompilationError() throws IOException {
|
||||
String sValue = null;
|
||||
try (InputStream input = new FileInputStream("src/main/resources/config.properties")) {
|
||||
try (InputStream input = new FileInputStream("src/test/resources/config.properties")) {
|
||||
Properties prop = new Properties();
|
||||
prop.load(input);
|
||||
sValue = prop.getProperty("string.too.long");
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
string.too.long="a long string example"
|
||||
@@ -0,0 +1,4 @@
|
||||
Get busy living
|
||||
or
|
||||
get busy dying.
|
||||
--Stephen King
|
||||
@@ -29,7 +29,37 @@
|
||||
<!--<module>core-java-serialization</module> -->
|
||||
<!--<module>core-java-streams-2</module> -->
|
||||
<!--<module>core-java-sun</module> -->
|
||||
|
||||
<module>core-java-9-improvements</module>
|
||||
<module>core-java-collections-array-list</module>
|
||||
<module>core-java-9-streams</module>
|
||||
<module>core-java-9</module>
|
||||
<module>core-java-10</module>
|
||||
<module>core-java-11</module>
|
||||
<module>core-java-11-2</module>
|
||||
<module>core-java-11-3</module>
|
||||
<module>core-java-collections-list-4</module>
|
||||
<module>core-java-collections-list-5</module>
|
||||
<module>core-java-collections-maps-4</module>
|
||||
<module>core-java-collections-maps-5</module>
|
||||
<module>core-java-concurrency-simple</module>
|
||||
<module>core-java-datetime-string</module>
|
||||
<module>core-java-io-conversions-2</module>
|
||||
<module>core-java-jpms</module>
|
||||
<module>core-java-lang-oop-constructors-2</module>
|
||||
<module>core-java-methods</module>
|
||||
<module>core-java-networking-3</module>
|
||||
<module>core-java-os</module>
|
||||
<!--<module>core-java-perf-2</module> Need to fix JAVA-24545 -->
|
||||
<module>core-java-streams-4</module>
|
||||
<module>core-java-streams-5</module>
|
||||
<module>core-java-streams-collect</module>
|
||||
<module>core-java-streams-maps</module>
|
||||
<module>core-java-string-algorithms-3</module>
|
||||
<module>core-java-string-operations-3</module>
|
||||
<module>core-java-string-operations-4</module>
|
||||
<module>core-java-string-operations-5</module>
|
||||
<!--<module>core-java-strings</module> Failing test cases JAVA-24414-->
|
||||
<module>core-java-time-measurements</module>
|
||||
<module>core-java-annotations</module>
|
||||
<module>core-java-arrays-sorting</module>
|
||||
<module>core-java-arrays-guides</module>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ADD . /project/
|
||||
ADD git-strategies /project/
|
||||
ADD /build/ /project/
|
||||
ADD /output/project.jar /project/
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
## Relevant articles:
|
||||
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>memory-leaks</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>memory-leaks</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../</relativePath>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources/</directory>
|
||||
<excludes>
|
||||
<exclude>**/*.java</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/test/resources/</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.baeldung;
|
||||
|
||||
public class Key {
|
||||
|
||||
public static String key;
|
||||
|
||||
public Key(String key) {
|
||||
Key.key = key;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
//package com.baeldung;
|
||||
//
|
||||
//import java.io.BufferedReader;
|
||||
//import java.io.File;
|
||||
//import java.io.IOException;
|
||||
//import java.io.InputStream;
|
||||
//import java.io.InputStreamReader;
|
||||
//import java.net.URISyntaxException;
|
||||
//import java.net.URL;
|
||||
//import java.net.URLConnection;
|
||||
//import java.nio.charset.StandardCharsets;
|
||||
//import java.nio.file.Files;
|
||||
//import java.nio.file.Paths;
|
||||
//import java.nio.file.StandardOpenOption;
|
||||
//import java.util.ArrayList;
|
||||
//import java.util.Map;
|
||||
//import java.util.Random;
|
||||
//import java.util.Scanner;
|
||||
//
|
||||
//import org.junit.FixMethodOrder;
|
||||
//import org.junit.Test;
|
||||
//import org.junit.runner.RunWith;
|
||||
//import org.junit.runners.JUnit4;
|
||||
//import org.junit.runners.MethodSorters;
|
||||
//
|
||||
//@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
//@RunWith(JUnit4.class)
|
||||
//public class MemoryLeaksTest {
|
||||
// private Random random = new Random();
|
||||
// public static final ArrayList<Double> list = new ArrayList<Double>(1000000);
|
||||
//
|
||||
// @Test
|
||||
// public void givenStaticField_whenLotsOfOperations_thenMemoryLeak() throws InterruptedException {
|
||||
// for (int i = 0; i < 1000000; i++) {
|
||||
// list.add(random.nextDouble());
|
||||
// }
|
||||
// System.gc();
|
||||
// Thread.sleep(10000); //to allow GC do its job
|
||||
// }
|
||||
//
|
||||
//
|
||||
// @Test
|
||||
// public void givenNormalField_whenLotsOfOperations_thenGCWorksFine() throws InterruptedException {
|
||||
// addElementsToTheList();
|
||||
// System.gc();
|
||||
// Thread.sleep(10000); //to allow GC do its job
|
||||
// }
|
||||
//
|
||||
// private void addElementsToTheList(){
|
||||
// ArrayList<Double> list = new ArrayList<Double>(1000000);
|
||||
// for (int i = 0; i < 1000000; i++) {
|
||||
// list.add(random.nextDouble());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @SuppressWarnings({ "resource" })
|
||||
// @Test(expected = OutOfMemoryError.class)
|
||||
// public void givenLengthString_whenIntern_thenOutOfMemory() throws IOException, InterruptedException {
|
||||
// Thread.sleep(15000);
|
||||
// String str = new Scanner(new File("src/test/resources/large.txt"), "UTF-8").useDelimiter("\\A")
|
||||
// .next();
|
||||
// System.gc();
|
||||
// str.intern();
|
||||
// Thread.sleep(10000);
|
||||
// }
|
||||
//
|
||||
// @Test(expected = OutOfMemoryError.class)
|
||||
// public void givenURL_whenUnclosedStream_thenOutOfMemory() throws IOException, URISyntaxException {
|
||||
// String str = "";
|
||||
// URLConnection conn = new URL("http:norvig.com/big.txt").openConnection();
|
||||
// BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
|
||||
// while (br.readLine() != null) {
|
||||
// str += br.readLine();
|
||||
// }
|
||||
// Files.write(Paths.get("src/main/resources/"), str.getBytes(), StandardOpenOption.CREATE);
|
||||
// }
|
||||
//
|
||||
// @SuppressWarnings("unused")
|
||||
// @Test(expected = OutOfMemoryError.class)
|
||||
// public void givenConnection_whenUnclosed_thenOutOfMemory() throws IOException, URISyntaxException {
|
||||
// URL url = new URL("ftp:speedtest.tele2.net");
|
||||
// URLConnection urlc = url.openConnection();
|
||||
// InputStream is = urlc.getInputStream();
|
||||
// String str = "";
|
||||
// while (true) {
|
||||
// str += is.toString()
|
||||
// .intern();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Test(expected = OutOfMemoryError.class)
|
||||
// public void givenMap_whenNoEqualsNoHashCodeMethods_thenOutOfMemory() throws IOException, URISyntaxException {
|
||||
// Map<Object, Object> map = System.getProperties();
|
||||
// while (true) {
|
||||
// map.put(new Key("key"), "value");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,2 @@
|
||||
## Relevant Articles
|
||||
- [@JsonSubTypes Vs. Reflections for Polymorphic Deserialization in Jackson](https://www.baeldung.com/java-jackson-polymorphic-deserialization)
|
||||
- [@JsonSubTypes vs. Reflections for Polymorphic Deserialization in Jackson](https://www.baeldung.com/java-jackson-polymorphic-deserialization)
|
||||
|
||||
@@ -16,9 +16,7 @@ public final class ExchangeRate {
|
||||
public static List<ExchangeRateProvider> providers() {
|
||||
List<ExchangeRateProvider> services = new ArrayList<>();
|
||||
ServiceLoader<ExchangeRateProvider> loader = ServiceLoader.load(ExchangeRateProvider.class);
|
||||
loader.forEach(exchangeRateProvider -> {
|
||||
services.add(exchangeRateProvider);
|
||||
});
|
||||
loader.forEach(services::add);
|
||||
return services;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,12 @@ public class Quote {
|
||||
private BigDecimal ask;
|
||||
private BigDecimal bid;
|
||||
private LocalDate date;
|
||||
//...
|
||||
|
||||
public Quote(String currency, BigDecimal ask, BigDecimal bid) {
|
||||
this.currency = currency;
|
||||
this.ask = ask;
|
||||
this.bid = bid;
|
||||
}
|
||||
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.baeldung.rate.impl;
|
||||
|
||||
import com.baeldung.rate.api.Quote;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class QuoteResponse {
|
||||
private List<Quote> result;
|
||||
private String error;
|
||||
|
||||
public List<Quote> getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(List<Quote> result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public void setError(String error) {
|
||||
this.error = error;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package com.baeldung.rate.impl;
|
||||
|
||||
public class QuoteResponseWrapper {
|
||||
private QuoteResponse quoteResponse;
|
||||
|
||||
public QuoteResponse getQuoteResponse() {
|
||||
return quoteResponse;
|
||||
}
|
||||
|
||||
public void setQuoteResponse(QuoteResponse quoteResponse) {
|
||||
this.quoteResponse = quoteResponse;
|
||||
}
|
||||
}
|
||||
@@ -2,64 +2,102 @@ package com.baeldung.rate.impl;
|
||||
|
||||
import com.baeldung.rate.api.Quote;
|
||||
import com.baeldung.rate.api.QuoteManager;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
import javax.json.bind.Jsonb;
|
||||
import javax.json.bind.JsonbBuilder;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Currency;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class YahooQuoteManagerImpl implements QuoteManager {
|
||||
|
||||
static final String URL_PROVIDER = "https://query1.finance.yahoo.com/v7/finance/quote";
|
||||
static final String URL_PROVIDER = "https://query2.finance.yahoo.com/v6/finance/quoteSummary/%s=X?modules=summaryDetail";
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
|
||||
@Override
|
||||
public List<Quote> getQuotes(String baseCurrency, LocalDate date) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
List<String> currencyQuery = new ArrayList<>();
|
||||
Currency.getAvailableCurrencies().forEach(currency -> {
|
||||
if (!baseCurrency.equals(currency.getCurrencyCode())) {
|
||||
sb.append(baseCurrency).append(currency.getCurrencyCode()).append("=X").append(",");
|
||||
currencyQuery.add(String.format(URL_PROVIDER, baseCurrency + currency.getCurrencyCode()));
|
||||
}
|
||||
});
|
||||
|
||||
String value = "";
|
||||
try {
|
||||
value = URLEncoder.encode(sb.toString().substring(0, sb.toString().length() - 1), "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
final List<Quote> quotes = new ArrayList<>();
|
||||
for (String url: currencyQuery) {
|
||||
String response = doGetRequest(url);
|
||||
if (response != null) {
|
||||
final Quote map = map(response);
|
||||
if (map != null) {
|
||||
quotes.add(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
String queryString = String.format("%s=%s", "symbols", value);
|
||||
String response = doGetRequest(queryString);
|
||||
System.out.println(response);
|
||||
return map(response);
|
||||
return quotes;
|
||||
}
|
||||
|
||||
private List<Quote> map(String response) {
|
||||
QuoteResponseWrapper qrw = JsonbBuilder.create().fromJson(response, QuoteResponseWrapper.class);
|
||||
return qrw.getQuoteResponse().getResult();
|
||||
private Quote map(String response) {
|
||||
try (final Jsonb jsonb = JsonbBuilder.create()) {
|
||||
final Map qrw = jsonb.fromJson(response, Map.class);
|
||||
return parseResult(qrw);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error while trying to read response");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String doGetRequest(String queryString) {
|
||||
String fullUrl = URL_PROVIDER + "?" + queryString;
|
||||
private static Quote parseResult(Map qrw) {
|
||||
Quote quote = null;
|
||||
if (qrw != null) {
|
||||
final Map quoteSummary = (Map) qrw.get("quoteSummary");
|
||||
if (quoteSummary != null) {
|
||||
final List<Map> result = (List<Map>) quoteSummary.get("result");
|
||||
if (result != null) {
|
||||
final Map resultArray = result.get(0);
|
||||
if (resultArray != null) {
|
||||
final Map summaryDetail = (Map) resultArray.get("summaryDetail");
|
||||
if (summaryDetail != null) {
|
||||
quote = constructQuote(summaryDetail);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return quote;
|
||||
}
|
||||
|
||||
System.out.println(fullUrl);
|
||||
private static Quote constructQuote(Map summaryDetail) {
|
||||
final String currency = (String) summaryDetail.get("currency");
|
||||
final Map ask = (Map) summaryDetail.get("ask");
|
||||
final Map bid = (Map) summaryDetail.get("bid");
|
||||
final BigDecimal askPrice = (BigDecimal) ask.get("raw");
|
||||
final BigDecimal bidPrice = (BigDecimal) bid.get("raw");
|
||||
if (askPrice != null && bidPrice != null) {
|
||||
return new Quote(currency, askPrice, bidPrice);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String doGetRequest(String url) {
|
||||
|
||||
System.out.println(url);
|
||||
Request request = new Request.Builder()
|
||||
.url(fullUrl)
|
||||
.url(url)
|
||||
.build();
|
||||
Response response = null;
|
||||
Response response;
|
||||
try {
|
||||
response = client.newCall(request).execute();
|
||||
return response.body().string();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
## JHipster 6
|
||||
|
||||
This module contains articles about JHipster 5. This is an aggregator module, articles are in the relevant submodules.
|
||||
This module contains articles about JHipster 6. This is an aggregator module, articles are in the relevant submodules.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.baeldung.jhipster6</groupId>
|
||||
<artifactId>bookstore-monolith</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
@@ -56,10 +55,6 @@
|
||||
<artifactId>jaxb-runtime</artifactId>
|
||||
<version>4.0.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-hibernate5</artifactId>
|
||||
@@ -649,6 +644,76 @@
|
||||
</pluginManagement>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>default-jdk9-and-above</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.github.eirslett</groupId>
|
||||
<artifactId>frontend-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>install node and npm</id>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>npm install</id>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>webpack build dev</id>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>webpack build test</id>
|
||||
<phase>none</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>integration-jdk9-and-above</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.github.eirslett</groupId>
|
||||
<artifactId>frontend-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>install node and npm</id>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>npm install</id>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>webpack build dev</id>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>webpack build test</id>
|
||||
<phase>none</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>no-liquibase</id>
|
||||
<properties>
|
||||
@@ -1098,7 +1163,7 @@
|
||||
|
||||
<!-- Plugin versions -->
|
||||
<maven-clean-plugin.version>3.1.0</maven-clean-plugin.version>
|
||||
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
|
||||
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
|
||||
<maven-eclipse-plugin.version>2.10</maven-eclipse-plugin.version>
|
||||
<maven-enforcer-plugin.version>3.0.0-M1</maven-enforcer-plugin.version>
|
||||
<maven-idea-plugin.version>2.2.1</maven-idea-plugin.version>
|
||||
|
||||
@@ -4,3 +4,4 @@ This module contains articles about JSON Conversions
|
||||
|
||||
### Relevant Articles:
|
||||
- [Convert JSON Array to Java List](https://www.baeldung.com/java-convert-json-array-to-list)
|
||||
- [Reading JSON Documents as Maps and Comparing Them](https://www.baeldung.com/java-json-maps-comparison)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<module>k8s-intro</module>
|
||||
<module>k8s-admission-controller</module>
|
||||
<module>kubernetes-spring</module>
|
||||
<module>k8s-java-heap-dump</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -13,4 +13,5 @@ This module contains articles about Project Lombok.
|
||||
- [@StandardException Annotation in Lombok](https://www.baeldung.com/lombok-standardexception-annotation)
|
||||
- [Lombok EqualsAndHashCode Annotation](https://www.baeldung.com/java-lombok-equalsandhashcode)
|
||||
- [Lombok’s @RequiredArgsConstructor Annotation](https://www.baeldung.com/java-lombok-constructor-annotation)
|
||||
- [Generate Models Using OpenAPI With Lombok Annotations](https://www.baeldung.com/java-openapi-lombok-create-models)
|
||||
- More articles: [[<-- prev]](../lombok)
|
||||
|
||||
@@ -11,3 +11,4 @@ This module contains articles about MapStruct.
|
||||
- [Mapping Collections with MapStruct](https://www.baeldung.com/java-mapstruct-mapping-collections)
|
||||
- [Use Mapper in Another Mapper with Mapstruct and Java](https://www.baeldung.com/java-mapstruct-nested-mapping)
|
||||
- [Throw Exception for Unexpected Input for Enum With MapStruct](https://www.baeldung.com/java-mapstruct-enum-unexpected-input-exception)
|
||||
- [How to Use Conditional Mapping With MapStruct](https://www.baeldung.com/java-mapstruct-bean-types-conditional)
|
||||
|
||||
@@ -3,13 +3,6 @@ package com.baeldung.expression.dto;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
@Builder
|
||||
public class LicenseDto {
|
||||
|
||||
private UUID id;
|
||||
@@ -18,4 +11,28 @@ public class LicenseDto {
|
||||
|
||||
private LocalDateTime endDate;
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public LocalDateTime getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(LocalDateTime startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public LocalDateTime getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(LocalDateTime endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,9 +3,7 @@ package com.baeldung.expression.model;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class License {
|
||||
|
||||
private UUID id;
|
||||
@@ -18,4 +16,43 @@ public class License {
|
||||
|
||||
private boolean renewalRequired;
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public OffsetDateTime getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(OffsetDateTime startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public OffsetDateTime getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(OffsetDateTime endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public boolean isRenewalRequired() {
|
||||
return renewalRequired;
|
||||
}
|
||||
|
||||
public void setRenewalRequired(boolean renewalRequired) {
|
||||
this.renewalRequired = renewalRequired;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
@@ -17,9 +18,9 @@ class LicenseMapperUnitTest {
|
||||
|
||||
@Test
|
||||
void givenLicenseDtoWithStartDateAndWithoutEndDate_WhenMapperMethodIsInvoked_ThenLicenseShouldBePopulatedWithDefaultEndDate() {
|
||||
License license = licenseMapper.toLicense(LicenseDto.builder()
|
||||
.startDate(LocalDateTime.now())
|
||||
.build());
|
||||
LicenseDto licenseDto = new LicenseDto();
|
||||
licenseDto.setStartDate(LocalDateTime.now());
|
||||
License license = licenseMapper.toLicense(licenseDto);
|
||||
assertThat(license).isNotNull();
|
||||
assertThat(license.getEndDate()
|
||||
.toLocalDate()).isEqualTo(LocalDate.now()
|
||||
@@ -28,10 +29,10 @@ class LicenseMapperUnitTest {
|
||||
|
||||
@Test
|
||||
void givenLicenseDtoWithEndDateAndWithoutStartDate_WhenMapperMethodIsInvoked_ThenLicenseShouldBePopulatedWithDefaultStartDate() {
|
||||
License license = licenseMapper.toLicense(LicenseDto.builder()
|
||||
.endDate(LocalDateTime.now()
|
||||
.plusYears(2))
|
||||
.build());
|
||||
LicenseDto licenseDto = new LicenseDto();
|
||||
licenseDto.setEndDate(LocalDateTime.now()
|
||||
.plusYears(2));
|
||||
License license = licenseMapper.toLicense(licenseDto);
|
||||
assertThat(license).isNotNull();
|
||||
assertThat(license.getStartDate()
|
||||
.toLocalDate()).isEqualTo(LocalDate.now());
|
||||
@@ -39,8 +40,8 @@ class LicenseMapperUnitTest {
|
||||
|
||||
@Test
|
||||
void givenLicenseDtoWithoutStartDateAndEndDate_WhenMapperMethodIsInvoked_ThenLicenseShouldBePopulatedWithDefaultDetails() {
|
||||
License license = licenseMapper.toLicense(LicenseDto.builder()
|
||||
.build());
|
||||
LicenseDto licenseDto = new LicenseDto();
|
||||
License license = licenseMapper.toLicense(licenseDto);
|
||||
assertThat(license).isNotNull();
|
||||
assertThat(license.getStartDate()
|
||||
.toLocalDate()).isEqualTo(LocalDate.now());
|
||||
@@ -53,12 +54,24 @@ class LicenseMapperUnitTest {
|
||||
|
||||
@Test
|
||||
void givenLicenseDtoWithEndDateInTwoWeeks_WhenMapperMethodIsInvoked_ThenLicenseShouldBePopulatedWithRenewalRequiredSetToTrue() {
|
||||
License license = licenseMapper.toLicense(LicenseDto.builder()
|
||||
.endDate(LocalDateTime.now()
|
||||
.plusDays(10))
|
||||
.build());
|
||||
LicenseDto licenseDto = new LicenseDto();
|
||||
licenseDto.setEndDate(LocalDateTime.now()
|
||||
.plusDays(10));
|
||||
License license = licenseMapper.toLicense(licenseDto);
|
||||
assertThat(license).isNotNull();
|
||||
assertThat(license.isRenewalRequired()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenLicenseDtoWithoutId_WhenMapperMethodIsInvoked_ThenLicenseShouldBePopulatedWithValidId() {
|
||||
LicenseDto licenseDto = new LicenseDto();
|
||||
UUID id = UUID.randomUUID();
|
||||
licenseDto.setId(id);
|
||||
licenseDto.setEndDate(LocalDateTime.now()
|
||||
.plusDays(10));
|
||||
License license = licenseMapper.toLicense(licenseDto);
|
||||
assertThat(license).isNotNull();
|
||||
assertThat(license.getId()).isSameAs(id);
|
||||
}
|
||||
|
||||
}
|
||||
2
maven-modules/jacoco-coverage-aggregation/README.md
Normal file
2
maven-modules/jacoco-coverage-aggregation/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
## Relevant Articles
|
||||
- [Maven Multi-Module Project Coverage With Jacoco](https://www.baeldung.com/maven-jacoco-multi-module-project)
|
||||
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.jacoco-coverage-aggregation</groupId>
|
||||
<artifactId>aggregate-report</artifactId>
|
||||
<name>aggregate-report</name>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>jacoco-coverage-aggregation</artifactId>
|
||||
<version>1.0</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.baeldung.jacoco-coverage-aggregation</groupId>
|
||||
<artifactId>services</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baeldung.jacoco-coverage-aggregation</groupId>
|
||||
<artifactId>controllers</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.8.8</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>report-aggregate</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<dataFileIncludes>
|
||||
<dataFileInclude>**/jacoco.exec</dataFileInclude>
|
||||
</dataFileIncludes>
|
||||
<outputDirectory>
|
||||
${project.reporting.outputDirectory}/jacoco-aggregate
|
||||
</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.jacoco-coverage-aggregation</groupId>
|
||||
<artifactId>controllers</artifactId>
|
||||
<name>controllers</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>jacoco-coverage-aggregation</artifactId>
|
||||
<version>1.0</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.baeldung.jacoco-coverage-aggregation</groupId>
|
||||
<artifactId>services</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>3.1.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*IntegrationTest.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<spring-boot.version>3.0.9</spring-boot.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.baeldung.coverageaggregation;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class MyApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MyApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.baeldung.coverageaggregation;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
class MyController {
|
||||
|
||||
private final MyService myService;
|
||||
|
||||
public MyController(MyService myService) {
|
||||
this.myService = myService;
|
||||
}
|
||||
|
||||
@GetMapping("/tested")
|
||||
String fullyTested() {
|
||||
return myService.coveredByUnitAndIntegrationTests();
|
||||
}
|
||||
|
||||
@GetMapping("/indirecttest")
|
||||
String indirectlyTestingServiceMethod() {
|
||||
return myService.coveredByIntegrationTest();
|
||||
}
|
||||
|
||||
@GetMapping("/nottested")
|
||||
String notTested() {
|
||||
return myService.notTested();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.baeldung.coverageaggregation;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
|
||||
|
||||
@SpringBootTest(classes = MyApplication.class)
|
||||
@AutoConfigureMockMvc
|
||||
class MyControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
void whenFullyTested_ThenCorrectText() throws Exception {
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/tested"))
|
||||
.andExpect(MockMvcResultMatchers.status()
|
||||
.isOk())
|
||||
.andExpect(MockMvcResultMatchers.content()
|
||||
.string("covered by unit and integration tests"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenIndirectlyTestingServiceMethod_ThenCorrectText() throws Exception {
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/indirecttest"))
|
||||
.andExpect(MockMvcResultMatchers.status()
|
||||
.isOk())
|
||||
.andExpect(MockMvcResultMatchers.content()
|
||||
.string("covered by integration test"));
|
||||
}
|
||||
|
||||
}
|
||||
42
maven-modules/jacoco-coverage-aggregation/pom.xml
Normal file
42
maven-modules/jacoco-coverage-aggregation/pom.xml
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>jacoco-coverage-aggregation</artifactId>
|
||||
<version>1.0</version>
|
||||
<name>jacoco-coverage-aggregation</name>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../</relativePath>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>services</module>
|
||||
<module>controllers</module>
|
||||
<module>aggregate-report</module>
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.8.8</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
52
maven-modules/jacoco-coverage-aggregation/services/pom.xml
Normal file
52
maven-modules/jacoco-coverage-aggregation/services/pom.xml
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.jacoco-coverage-aggregation</groupId>
|
||||
<artifactId>services</artifactId>
|
||||
<name>services</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>jacoco-coverage-aggregation</artifactId>
|
||||
<version>1.0</version>
|
||||
</parent>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring-context.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${junit-jupiter-engine.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.1.2</version>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*Test.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<junit-jupiter-engine.version>5.9.2</junit-jupiter-engine.version>
|
||||
<spring-context.version>6.0.11</spring-context.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.baeldung.coverageaggregation;
|
||||
|
||||
import java.lang.String;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
class MyService {
|
||||
|
||||
String unitTestedOnly() {
|
||||
return "unit tested only";
|
||||
}
|
||||
|
||||
String coveredByUnitAndIntegrationTests() {
|
||||
return "covered by unit and integration tests";
|
||||
}
|
||||
|
||||
String coveredByIntegrationTest() {
|
||||
return "covered by integration test";
|
||||
}
|
||||
|
||||
String notTested() {
|
||||
return "not tested";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.coverageaggregation;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class MyServiceUnitTest {
|
||||
|
||||
MyService myService = new MyService();
|
||||
|
||||
@Test
|
||||
void whenUnitTestedOnly_thenCorrectText() {
|
||||
assertEquals("unit tested only", myService.unitTestedOnly());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenTestedMethod_thenCorrectText() {
|
||||
assertEquals("covered by unit and integration tests", myService.coveredByUnitAndIntegrationTests());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
<module>compiler-plugin-java-9</module>
|
||||
<module>dependency-exclusion</module>
|
||||
<module>host-maven-repo-example</module>
|
||||
<module>jacoco-coverage-aggregation</module>
|
||||
<module>maven-archetype</module>
|
||||
<module>maven-build-optimization</module>
|
||||
<module>maven-builder-plugin</module>
|
||||
@@ -46,6 +47,9 @@
|
||||
<module>version-collision</module>
|
||||
<module>version-overriding-plugins</module>
|
||||
<module>versions-maven-plugin</module>
|
||||
<module>maven-pom-types</module>
|
||||
<module>multimodulemavenproject</module>
|
||||
<module>resume-from</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.creational.abstractfactory2;
|
||||
|
||||
public class AbstractFactoryRunner {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new AnimalAbstractFactory().createAnimal(AnimalType.LAND);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.creational.abstractfactory2;
|
||||
|
||||
public abstract class Animal {
|
||||
AnimalType type;
|
||||
AnimalEra era;
|
||||
String name;
|
||||
Animal(AnimalType type, AnimalEra era, String name) {
|
||||
this.type = type;
|
||||
this.era = era;
|
||||
this.name = name;
|
||||
}
|
||||
abstract void create();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.baeldung.creational.abstractfactory2;
|
||||
|
||||
public class AnimalAbstractFactory {
|
||||
|
||||
Animal animal;
|
||||
Animal createAnimal(AnimalType type) {
|
||||
AnimalEra era = getFromConfiguration();
|
||||
switch (era) {
|
||||
case MESOZOIC:
|
||||
animal = new MesozoicAnimalFactory().createAnimal(type);
|
||||
break;
|
||||
case CENOZOIC:
|
||||
animal = new CenozoicAnimalFactory().createAnimal(type);
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
AnimalEra getFromConfiguration() {
|
||||
return AnimalEra.MESOZOIC;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.baeldung.creational.abstractfactory2;
|
||||
|
||||
public enum AnimalEra {
|
||||
MESOZOIC,
|
||||
CENOZOIC
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.baeldung.creational.abstractfactory2;
|
||||
|
||||
public enum AnimalType {
|
||||
LAND,
|
||||
SKY
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.creational.abstractfactory2;
|
||||
|
||||
public class CenozoicAnimalFactory implements EraAnimalFactory{
|
||||
@Override
|
||||
public LandAnimal makeLandAnimal() {
|
||||
return new LandAnimal(AnimalEra.CENOZOIC, "Mammoth");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkyAnimal makeSkyAnimal() {
|
||||
return new SkyAnimal(AnimalEra.CENOZOIC, "Terror bird");
|
||||
}
|
||||
|
||||
Animal createAnimal(AnimalType type) {
|
||||
switch (type) {
|
||||
case LAND:
|
||||
return makeLandAnimal();
|
||||
case SKY:
|
||||
return makeSkyAnimal();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.baeldung.creational.abstractfactory2;
|
||||
|
||||
public interface EraAnimalFactory {
|
||||
|
||||
LandAnimal makeLandAnimal();
|
||||
SkyAnimal makeSkyAnimal();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.creational.abstractfactory2;
|
||||
|
||||
public class LandAnimal extends Animal{
|
||||
|
||||
LandAnimal(AnimalEra era, String name) {
|
||||
super(AnimalType.LAND, era, name);
|
||||
create();
|
||||
}
|
||||
@Override
|
||||
void create() {
|
||||
System.out.println("Creating a " + type + " animal: " + name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.creational.abstractfactory2;
|
||||
|
||||
public class MesozoicAnimalFactory implements EraAnimalFactory{
|
||||
@Override
|
||||
public LandAnimal makeLandAnimal() {
|
||||
return new LandAnimal(AnimalEra.MESOZOIC, "Tyrannosaurus Rex");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkyAnimal makeSkyAnimal() {
|
||||
return new SkyAnimal(AnimalEra.MESOZOIC, "Pterodactylus");
|
||||
}
|
||||
|
||||
Animal createAnimal(AnimalType type) {
|
||||
switch (type) {
|
||||
case LAND:
|
||||
return makeLandAnimal();
|
||||
case SKY:
|
||||
return makeSkyAnimal();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.creational.abstractfactory2;
|
||||
|
||||
public class SkyAnimal extends Animal{
|
||||
|
||||
SkyAnimal(AnimalEra era, String name) {
|
||||
super(AnimalType.SKY, era, name);
|
||||
create();
|
||||
}
|
||||
@Override
|
||||
void create() {
|
||||
System.out.println("Creating a " + type + " animal: " + name);
|
||||
}
|
||||
}
|
||||
@@ -113,6 +113,10 @@
|
||||
<module>java-mongodb</module>
|
||||
<module>questdb</module>
|
||||
<module>neo4j</module>
|
||||
<module>rethinkdb</module>
|
||||
<module>scylladb</module>
|
||||
<module>spring-data-cassandra-2</module>
|
||||
<!--<module>spring-data-jpa-repo-3</module>--> <!--Fix in JAVA-24547-->
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
||||
@@ -8,77 +8,56 @@
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-spring-5</artifactId>
|
||||
<artifactId>parent-boot-3</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-spring-5</relativePath>
|
||||
<relativePath>../../parent-boot-3</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-elasticsearch</artifactId>
|
||||
<version>${spring-data-elasticsearch.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.elasticsearch</groupId>
|
||||
<artifactId>elasticsearch</artifactId>
|
||||
<version>${elasticsearch.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
<!--These two dependencies are inherited from spring-data-elasticsearch. Overriding to the newer version
|
||||
will break tests. -->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>co.elastic.clients</groupId>-->
|
||||
<!-- <artifactId>elasticsearch-java</artifactId>-->
|
||||
<!-- <version>${elasticsearch.version}</version>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.fasterxml.jackson.core</groupId>-->
|
||||
<!-- <artifactId>jackson-databind</artifactId>-->
|
||||
<!-- <version>${jackson.version}</version>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- Here for backward compatibility-->
|
||||
<dependency>
|
||||
<groupId>org.elasticsearch.client</groupId>
|
||||
<artifactId>elasticsearch-rest-high-level-client</artifactId>
|
||||
<version>7.17.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.28</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.locationtech.spatial4j</groupId>
|
||||
<artifactId>spatial4j</artifactId>
|
||||
<version>${spatial4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.locationtech.jts</groupId>
|
||||
<artifactId>jts-core</artifactId>
|
||||
<version>${jts.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>xerces</groupId>
|
||||
<artifactId>xercesImpl</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>test</scope>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<properties>
|
||||
<spring-data-elasticsearch.version>5.1.2</spring-data-elasticsearch.version>
|
||||
<elasticsearch.version>8.9.0</elasticsearch.version>
|
||||
<fastjson.version>2.0.37</fastjson.version>
|
||||
<spatial4j.version>0.8</spatial4j.version>
|
||||
<jts.version>1.18.2</jts.version>
|
||||
<jackson.version>2.15.2</jackson.version>
|
||||
</properties>
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.baeldung;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.baeldung.elasticsearch;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Location {
|
||||
|
||||
private String name;
|
||||
private List<Double> location;
|
||||
}
|
||||
@@ -12,8 +12,6 @@ import java.util.Date;
|
||||
public class Person {
|
||||
|
||||
private int age;
|
||||
|
||||
private String fullName;
|
||||
|
||||
private Date dateOfBirth;
|
||||
}
|
||||
|
||||
@@ -15,18 +15,18 @@ import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
||||
import co.elastic.clients.transport.rest_client.RestClientTransport;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.elasticsearch.client.RestClient;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* This Manual test requires: Elasticsearch instance running on localhost:9200.
|
||||
@@ -35,41 +35,35 @@ import static org.junit.Assert.assertEquals;
|
||||
* docker run -d --name elastic-test -p 9200:9200 -e "discovery.type=single-node" -e "xpack.security.enabled=false" docker.elastic.co/elasticsearch/elasticsearch:8.9.0
|
||||
*/
|
||||
@Slf4j
|
||||
@Disabled("Manual test")
|
||||
public class ElasticSearchManualTest {
|
||||
private ElasticsearchClient client = null;
|
||||
|
||||
@Before
|
||||
@BeforeEach
|
||||
public void setUp() throws IOException {
|
||||
RestClient restClient = RestClient
|
||||
.builder(HttpHost.create("http://localhost:9200"))
|
||||
.build();
|
||||
RestClient restClient = RestClient.builder(HttpHost.create("http://localhost:9200"))
|
||||
.build();
|
||||
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
|
||||
client = new ElasticsearchClient(transport);
|
||||
Person person1 = new Person(10, "John Doe", new Date());
|
||||
Person person2 = new Person(25, "Janette Doe", new Date());
|
||||
Person person3 = new Person(8, "Mark Doe", new Date());
|
||||
client.index(builder -> builder
|
||||
.index("person")
|
||||
.id(person1.getFullName())
|
||||
.document(person1));
|
||||
client.index(builder -> builder
|
||||
.index("person")
|
||||
.id(person2.getFullName())
|
||||
.document(person2));
|
||||
client.index(builder -> builder
|
||||
.index("person")
|
||||
.id(person3.getFullName())
|
||||
.document(person3));
|
||||
client.index(builder -> builder.index("person")
|
||||
.id(person1.getFullName())
|
||||
.document(person1));
|
||||
client.index(builder -> builder.index("person")
|
||||
.id(person2.getFullName())
|
||||
.document(person2));
|
||||
client.index(builder -> builder.index("person")
|
||||
.id(person3.getFullName())
|
||||
.document(person3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenJsonDocument_whenJavaObject_thenIndexDocument() throws Exception {
|
||||
Person person = new Person(20, "Mark Doe", new Date(1471466076564L));
|
||||
IndexResponse response = client.index(i -> i
|
||||
.index("person")
|
||||
.id(person.getFullName())
|
||||
.document(person));
|
||||
IndexResponse response = client.index(i -> i.index("person")
|
||||
.id(person.getFullName())
|
||||
.document(person));
|
||||
|
||||
log.info("Indexed with version: {}", response.version());
|
||||
assertEquals(Result.Created, response.result());
|
||||
@@ -81,10 +75,9 @@ public class ElasticSearchManualTest {
|
||||
public void givenJsonString_whenJavaObject_thenIndexDocument() throws Exception {
|
||||
String jsonString = "{\"age\":10,\"dateOfBirth\":1471466076564,\"fullName\":\"John Doe\"}";
|
||||
StringReader stringReader = new StringReader(jsonString);
|
||||
IndexResponse response = client.index(i -> i
|
||||
.index("person")
|
||||
.id("John Doe")
|
||||
.withJson(stringReader));
|
||||
IndexResponse response = client.index(i -> i.index("person")
|
||||
.id("John Doe")
|
||||
.withJson(stringReader));
|
||||
log.info("Indexed with version: {}", response.version());
|
||||
assertEquals("person", response.index());
|
||||
assertEquals("John Doe", response.id());
|
||||
@@ -93,9 +86,8 @@ public class ElasticSearchManualTest {
|
||||
@Test
|
||||
public void givenDocumentId_whenJavaObject_thenDeleteDocument() throws Exception {
|
||||
String documentId = "Mark Doe";
|
||||
DeleteResponse response = client.delete(i -> i
|
||||
.index("person")
|
||||
.id(documentId));
|
||||
DeleteResponse response = client.delete(i -> i.index("person")
|
||||
.id(documentId));
|
||||
assertEquals(Result.Deleted, response.result());
|
||||
assertEquals("Mark Doe", response.id());
|
||||
}
|
||||
@@ -103,24 +95,23 @@ public class ElasticSearchManualTest {
|
||||
@Test
|
||||
public void givenSearchRequest_whenMatch_thenReturnAllResults() throws Exception {
|
||||
String searchText = "John";
|
||||
SearchResponse<Person> searchResponse = client.search(s -> s
|
||||
.index("person")
|
||||
.query(q -> q
|
||||
.match(t -> t
|
||||
.field("fullName")
|
||||
.query(searchText))), Person.class);
|
||||
SearchResponse<Person> searchResponse = client.search(s -> s.index("person")
|
||||
.query(q -> q.match(t -> t.field("fullName")
|
||||
.query(searchText))), Person.class);
|
||||
|
||||
List<Hit<Person>> hits = searchResponse.hits().hits();
|
||||
List<Hit<Person>> hits = searchResponse.hits()
|
||||
.hits();
|
||||
assertEquals(1, hits.size());
|
||||
assertEquals("John Doe", hits.get(0).source().getFullName());
|
||||
assertEquals("John Doe", hits.get(0)
|
||||
.source()
|
||||
.getFullName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenGetRequest_whenMatch_thenReturnAllResults() throws IOException {
|
||||
String documentId = "John Doe";
|
||||
GetResponse<Person> getResponse = client.get(s -> s
|
||||
.index("person")
|
||||
.id(documentId), Person.class);
|
||||
GetResponse<Person> getResponse = client.get(s -> s.index("person")
|
||||
.id(documentId), Person.class);
|
||||
Person source = getResponse.source();
|
||||
assertEquals("John Doe", source.getFullName());
|
||||
}
|
||||
@@ -128,47 +119,58 @@ public class ElasticSearchManualTest {
|
||||
@Test
|
||||
public void givenSearchRequest_whenMatchAndRange_thenReturnAllResults() throws Exception {
|
||||
String searchText = "John";
|
||||
SearchResponse<Person> searchResponse = client.search(s -> s
|
||||
.index("person")
|
||||
.query(q -> q
|
||||
.match(t -> t
|
||||
.field("fullName").query(searchText)))
|
||||
.query(q -> q
|
||||
.range(range -> range
|
||||
.field("age").from("1").to("10"))),
|
||||
Person.class);
|
||||
SearchResponse<Person> searchResponse = client.search(s -> s.index("person")
|
||||
.query(q -> q.match(t -> t.field("fullName")
|
||||
.query(searchText)))
|
||||
.query(q -> q.range(range -> range.field("age")
|
||||
.from("1")
|
||||
.to("10"))), Person.class);
|
||||
|
||||
List<Hit<Person>> hits = searchResponse.hits().hits();
|
||||
List<Hit<Person>> hits = searchResponse.hits()
|
||||
.hits();
|
||||
assertEquals(1, hits.size());
|
||||
assertEquals("John Doe", hits.get(0).source().getFullName());
|
||||
assertEquals("John Doe", hits.get(0)
|
||||
.source()
|
||||
.getFullName());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void givenMultipleQueries_thenReturnResults() throws Exception {
|
||||
Query ageQuery = RangeQuery.of(r -> r.field("age").from("5").to("15"))._toQuery();
|
||||
SearchResponse<Person> response1 = client.search(s -> s.query(q -> q.bool(b -> b
|
||||
.must(ageQuery))), Person.class);
|
||||
response1.hits().hits().forEach(hit -> log.info("Response 1: {}", hit.source()));
|
||||
Query ageQuery = RangeQuery.of(r -> r.field("age")
|
||||
.from("5")
|
||||
.to("15"))
|
||||
._toQuery();
|
||||
SearchResponse<Person> response1 = client.search(s -> s.query(q -> q.bool(b -> b.must(ageQuery))), Person.class);
|
||||
response1.hits()
|
||||
.hits()
|
||||
.forEach(hit -> log.info("Response 1: {}", hit.source()));
|
||||
|
||||
Query fullNameQuery = MatchQuery.of(m -> m.field("fullName").query("John"))._toQuery();
|
||||
SearchResponse<Person> response2 = client.search(s -> s.query(q -> q.bool(b -> b
|
||||
.must(fullNameQuery))), Person.class);
|
||||
response2.hits().hits().forEach(hit -> log.info("Response 2: {}", hit.source()));
|
||||
Query doeContainsQuery = SimpleQueryStringQuery.of(q -> q.query("*Doe"))._toQuery();
|
||||
SearchResponse<Person> response3 = client.search(s -> s.query(q -> q.bool(b -> b
|
||||
.must(doeContainsQuery))), Person.class);
|
||||
response3.hits().hits().forEach(hit -> log.info("Response 3: {}", hit.source()));
|
||||
Query fullNameQuery = MatchQuery.of(m -> m.field("fullName")
|
||||
.query("John"))
|
||||
._toQuery();
|
||||
SearchResponse<Person> response2 = client.search(s -> s.query(q -> q.bool(b -> b.must(fullNameQuery))), Person.class);
|
||||
response2.hits()
|
||||
.hits()
|
||||
.forEach(hit -> log.info("Response 2: {}", hit.source()));
|
||||
Query doeContainsQuery = SimpleQueryStringQuery.of(q -> q.query("*Doe"))
|
||||
._toQuery();
|
||||
SearchResponse<Person> response3 = client.search(s -> s.query(q -> q.bool(b -> b.must(doeContainsQuery))), Person.class);
|
||||
response3.hits()
|
||||
.hits()
|
||||
.forEach(hit -> log.info("Response 3: {}", hit.source()));
|
||||
|
||||
Query simpleStringQuery = SimpleQueryStringQuery.of(q -> q.query("+John -Doe OR Janette"))._toQuery();
|
||||
SearchResponse<Person> response4 = client.search(s -> s.query(q -> q.bool(b -> b
|
||||
.must(simpleStringQuery))), Person.class);
|
||||
response4.hits().hits().forEach(hit -> log.info("Response 4: {}", hit.source()));
|
||||
Query simpleStringQuery = SimpleQueryStringQuery.of(q -> q.query("+John -Doe OR Janette"))
|
||||
._toQuery();
|
||||
SearchResponse<Person> response4 = client.search(s -> s.query(q -> q.bool(b -> b.must(simpleStringQuery))), Person.class);
|
||||
response4.hits()
|
||||
.hits()
|
||||
.forEach(hit -> log.info("Response 4: {}", hit.source()));
|
||||
|
||||
SearchResponse<Person> response5 = client.search(s -> s.query(q -> q.bool(b -> b
|
||||
.must(ageQuery)
|
||||
.must(fullNameQuery)
|
||||
.must(simpleStringQuery))), Person.class);
|
||||
response5.hits().hits().forEach(hit -> log.info("Response 5: {}", hit.source()));
|
||||
SearchResponse<Person> response5 = client.search(s -> s.query(q -> q.bool(b -> b.must(ageQuery)
|
||||
.must(fullNameQuery)
|
||||
.must(simpleStringQuery))), Person.class);
|
||||
response5.hits()
|
||||
.hits()
|
||||
.forEach(hit -> log.info("Response 5: {}", hit.source()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,199 +1,198 @@
|
||||
package com.baeldung.elasticsearch;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
||||
import co.elastic.clients.elasticsearch._types.GeoShapeRelation;
|
||||
import co.elastic.clients.elasticsearch.core.IndexResponse;
|
||||
import co.elastic.clients.elasticsearch.core.SearchRequest;
|
||||
import co.elastic.clients.elasticsearch.core.SearchResponse;
|
||||
import co.elastic.clients.elasticsearch.core.search.Hit;
|
||||
import co.elastic.clients.json.JsonData;
|
||||
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
||||
import co.elastic.clients.transport.rest_client.RestClientTransport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.io.StringReader;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.baeldung.spring.data.es.config.Config;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.index.IndexResponse;
|
||||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.elasticsearch.client.indices.CreateIndexRequest;
|
||||
import org.elasticsearch.common.geo.GeoPoint;
|
||||
import org.elasticsearch.common.geo.ShapeRelation;
|
||||
import org.elasticsearch.common.unit.DistanceUnit;
|
||||
import org.elasticsearch.index.query.GeoShapeQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.xcontent.XContentType;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.locationtech.jts.geom.Coordinate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.elasticsearch.client.RestClient;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* This Manual test requires: Elasticsearch instance running on localhost:9200.
|
||||
*
|
||||
* The following docker command can be used: docker run -d --name es762 -p
|
||||
* 9200:9200 -e "discovery.type=single-node" elasticsearch:7.6.2
|
||||
* <p>
|
||||
* The following docker command can be used: docker run -d --name elastic-test -p 9200:9200 -e
|
||||
* "discovery.type=single-node" -e "xpack.security.enabled=false"
|
||||
* docker.elastic.co/elasticsearch/elasticsearch:8.9.0
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = Config.class)
|
||||
public class GeoQueriesManualTest {
|
||||
|
||||
@Slf4j
|
||||
class GeoQueriesManualTest {
|
||||
|
||||
private static final String WONDERS_OF_WORLD = "wonders-of-world";
|
||||
|
||||
@Autowired
|
||||
private RestHighLevelClient client;
|
||||
private ElasticsearchClient client;
|
||||
|
||||
@Before
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
String jsonObject = "{\"properties\":{\"name\":{\"type\":\"text\",\"index\":false},\"region\":{\"type\":\"geo_shape\"},\"location\":{\"type\":\"geo_point\"}}}";
|
||||
|
||||
CreateIndexRequest req = new CreateIndexRequest(WONDERS_OF_WORLD);
|
||||
req.mapping(jsonObject, XContentType.JSON);
|
||||
|
||||
RestClient restClient = RestClient.builder(HttpHost.create("http://localhost:9200"))
|
||||
.build();
|
||||
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
|
||||
client = new ElasticsearchClient(transport);
|
||||
log.info("Creating index: {}", WONDERS_OF_WORLD);
|
||||
client.indices()
|
||||
.create(req, RequestOptions.DEFAULT);
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void givenGeoShapeData_whenExecutedGeoShapeQuery_thenResultNonEmpty() throws IOException {
|
||||
// String jsonObject = "{\"name\":\"Agra\",\"region\":{\"type\":\"envelope\",\"coordinates\":[[75,30.2],[80.1, 25]]}}";
|
||||
// IndexRequest indexRequest = new IndexRequest(WONDERS_OF_WORLD);
|
||||
// indexRequest.source(jsonObject, XContentType.JSON);
|
||||
// IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
|
||||
//
|
||||
// String tajMahalId = response.getId();
|
||||
//
|
||||
// RefreshRequest refreshRequest = new RefreshRequest(WONDERS_OF_WORLD);
|
||||
// client.indices()
|
||||
// .refresh(refreshRequest, RequestOptions.DEFAULT);
|
||||
//
|
||||
// Coordinate topLeft = new Coordinate(74, 31.2);
|
||||
// Coordinate bottomRight = new Coordinate(81.1, 24);
|
||||
//
|
||||
// GeoShapeQueryBuilder qb = QueryBuilders.geoShapeQuery("region", new EnvelopeBuilder(topLeft, bottomRight).buildGeometry());
|
||||
// qb.relation(ShapeRelation.INTERSECTS);
|
||||
//
|
||||
// SearchSourceBuilder source = new SearchSourceBuilder().query(qb);
|
||||
// SearchRequest searchRequest = new SearchRequest(WONDERS_OF_WORLD);
|
||||
// searchRequest.source(source);
|
||||
//
|
||||
// SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
|
||||
//
|
||||
// List<String> ids = Arrays.stream(searchResponse.getHits()
|
||||
// .getHits())
|
||||
// .map(SearchHit::getId)
|
||||
// .collect(Collectors.toList());
|
||||
//
|
||||
// assertTrue(ids.contains(tajMahalId));
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void givenGeoPointData_whenExecutedGeoBoundingBoxQuery_thenResultNonEmpty() throws Exception {
|
||||
String jsonObject = "{\"name\":\"Pyramids of Giza\",\"location\":[31.131302,29.976480]}";
|
||||
|
||||
IndexRequest indexRequest = new IndexRequest(WONDERS_OF_WORLD);
|
||||
indexRequest.source(jsonObject, XContentType.JSON);
|
||||
IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
|
||||
|
||||
String pyramidsOfGizaId = response.getId();
|
||||
|
||||
RefreshRequest refreshRequest = new RefreshRequest(WONDERS_OF_WORLD);
|
||||
client.indices()
|
||||
.refresh(refreshRequest, RequestOptions.DEFAULT);
|
||||
|
||||
QueryBuilder qb = QueryBuilders.geoBoundingBoxQuery("location")
|
||||
.setCorners(31, 30, 28, 32);
|
||||
|
||||
SearchSourceBuilder source = new SearchSourceBuilder().query(qb);
|
||||
SearchRequest searchRequest = new SearchRequest(WONDERS_OF_WORLD);
|
||||
searchRequest.source(source);
|
||||
|
||||
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
|
||||
|
||||
List<String> ids = Arrays.stream(searchResponse.getHits()
|
||||
.getHits())
|
||||
.map(SearchHit::getId)
|
||||
.collect(Collectors.toList());
|
||||
assertTrue(ids.contains(pyramidsOfGizaId));
|
||||
.create(builder -> builder.index(WONDERS_OF_WORLD)
|
||||
.mappings(typeMapping -> typeMapping.properties("region", region -> region.geoShape(gs -> gs))
|
||||
.properties("location", location -> location.geoPoint(gp -> gp))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenGeoPointData_whenExecutedGeoDistanceQuery_thenResultNonEmpty() throws Exception {
|
||||
String jsonObject = "{\"name\":\"Lighthouse of alexandria\",\"location\":[31.131302,29.976480]}";
|
||||
void givenGeoShapeData_whenExecutedGeoShapeQuery_thenResultNonEmpty() throws IOException {
|
||||
String jsonObject = """
|
||||
{
|
||||
"name":"Agra",
|
||||
"region":{
|
||||
"type":"envelope",
|
||||
"coordinates":[[75,30.2],[80.1,25]]
|
||||
}
|
||||
}
|
||||
""";
|
||||
IndexResponse response = client.index(idx -> idx.index(WONDERS_OF_WORLD)
|
||||
.withJson(new StringReader(jsonObject)));
|
||||
|
||||
IndexRequest indexRequest = new IndexRequest(WONDERS_OF_WORLD);
|
||||
indexRequest.source(jsonObject, XContentType.JSON);
|
||||
IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
|
||||
|
||||
String lighthouseOfAlexandriaId = response.getId();
|
||||
|
||||
RefreshRequest refreshRequest = new RefreshRequest(WONDERS_OF_WORLD);
|
||||
String tajMahalId = response.id();
|
||||
client.indices()
|
||||
.refresh(refreshRequest, RequestOptions.DEFAULT);
|
||||
.refresh();
|
||||
|
||||
QueryBuilder qb = QueryBuilders.geoDistanceQuery("location")
|
||||
.point(29.976, 31.131)
|
||||
.distance(10, DistanceUnit.MILES);
|
||||
StringReader jsonData = new StringReader("""
|
||||
{
|
||||
"type":"envelope",
|
||||
"coordinates": [[74.0, 31.2], [81.1, 24.0 ] ]
|
||||
}
|
||||
""");
|
||||
|
||||
SearchSourceBuilder source = new SearchSourceBuilder().query(qb);
|
||||
SearchRequest searchRequest = new SearchRequest(WONDERS_OF_WORLD);
|
||||
searchRequest.source(source);
|
||||
|
||||
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
|
||||
|
||||
List<String> ids = Arrays.stream(searchResponse.getHits()
|
||||
.getHits())
|
||||
.map(SearchHit::getId)
|
||||
.collect(Collectors.toList());
|
||||
assertTrue(ids.contains(lighthouseOfAlexandriaId));
|
||||
SearchRequest searchRequest = new SearchRequest.Builder().query(query -> query.bool(boolQuery -> boolQuery.filter(query1 -> query1.geoShape(geoShapeQuery -> geoShapeQuery.field("region")
|
||||
.shape(geoShapeFieldQuery -> geoShapeFieldQuery.relation(GeoShapeRelation.Within)
|
||||
.shape(JsonData.from(jsonData)))))))
|
||||
.build();
|
||||
log.info("Search request: {}", searchRequest);
|
||||
SearchResponse<Object> search = client.search(searchRequest, Object.class);
|
||||
log.info("Search response: {}", search);
|
||||
List<String> searchResults = search.hits()
|
||||
.hits()
|
||||
.stream()
|
||||
.map(Hit::id)
|
||||
.toList();
|
||||
assertTrue(searchResults.contains(tajMahalId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenGeoPointData_whenExecutedGeoPolygonQuery_thenResultNonEmpty() throws Exception {
|
||||
String jsonObject = "{\"name\":\"The Great Rann of Kutch\",\"location\":[69.859741,23.733732]}";
|
||||
void givenGeoPointData_whenExecutedGeoBoundingBoxQuery_thenResultNonEmpty() throws Exception {
|
||||
Location pyramidsOfGiza = new Location("Pyramids of Giza", List.of(31.1328, 29.9761));
|
||||
IndexResponse response = client.index(builder -> builder.index(WONDERS_OF_WORLD)
|
||||
.document(pyramidsOfGiza));
|
||||
|
||||
IndexRequest indexRequest = new IndexRequest(WONDERS_OF_WORLD);
|
||||
indexRequest.source(jsonObject, XContentType.JSON);
|
||||
IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
|
||||
String pyramidsOfGizaId = response.id();
|
||||
|
||||
String greatRannOfKutchid = response.getId();
|
||||
|
||||
RefreshRequest refreshRequest = new RefreshRequest(WONDERS_OF_WORLD);
|
||||
log.info("Indexed pyramid of Giza: {}", pyramidsOfGizaId);
|
||||
client.indices()
|
||||
.refresh(refreshRequest, RequestOptions.DEFAULT);
|
||||
.refresh();
|
||||
|
||||
List<GeoPoint> allPoints = new ArrayList<GeoPoint>();
|
||||
allPoints.add(new GeoPoint(22.733, 68.859));
|
||||
allPoints.add(new GeoPoint(24.733, 68.859));
|
||||
allPoints.add(new GeoPoint(23, 70.859));
|
||||
QueryBuilder qb = QueryBuilders.geoPolygonQuery("location", allPoints);
|
||||
|
||||
SearchSourceBuilder source = new SearchSourceBuilder().query(qb);
|
||||
SearchRequest searchRequest = new SearchRequest(WONDERS_OF_WORLD);
|
||||
searchRequest.source(source);
|
||||
|
||||
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
|
||||
|
||||
List<String> ids = Arrays.stream(searchResponse.getHits()
|
||||
.getHits())
|
||||
.map(SearchHit::getId)
|
||||
.collect(Collectors.toList());
|
||||
assertTrue(ids.contains(greatRannOfKutchid));
|
||||
SearchRequest.Builder builder = new SearchRequest.Builder().index(WONDERS_OF_WORLD);
|
||||
builder.query(query -> query.geoBoundingBox(geoBoundingBoxQuery -> geoBoundingBoxQuery.field("location")
|
||||
.boundingBox(geoBounds -> geoBounds.tlbr(bl4 -> bl4.topLeft(geoLocation -> geoLocation.coords(List.of(30.0, 31.0)))
|
||||
.bottomRight(geoLocation -> geoLocation.coords(List.of(32.0, 28.0)))))));
|
||||
SearchRequest build = builder.build();
|
||||
log.info("Search request: {}", build);
|
||||
SearchResponse<Location> searchResponse = client.search(build, Location.class);
|
||||
log.info("Search response: {}", searchResponse);
|
||||
List<Location> returnedLocations = searchResponse.hits()
|
||||
.hits()
|
||||
.stream()
|
||||
.map(Hit::source)
|
||||
.toList();
|
||||
assertEquals(pyramidsOfGiza, returnedLocations.get(0));
|
||||
}
|
||||
|
||||
@After
|
||||
@Test
|
||||
void givenGeoPointData_whenExecutedGeoDistanceQuery_thenResultNonEmpty() throws Exception {
|
||||
String jsonObject = """
|
||||
{
|
||||
"name":"Lighthouse of alexandria",
|
||||
"location":{ "lat": 31.2139, "lon": 29.8856 }
|
||||
}
|
||||
""";
|
||||
IndexResponse response = client.index(idx -> idx.index(WONDERS_OF_WORLD)
|
||||
.withJson(new StringReader(jsonObject)));
|
||||
|
||||
String lightHouseOfAlexandriaId = response.id();
|
||||
client.indices()
|
||||
.refresh();
|
||||
SearchRequest searchRequest = new SearchRequest.Builder().index(WONDERS_OF_WORLD)
|
||||
.query(query -> query.geoDistance(geoDistanceQuery -> geoDistanceQuery.field("location")
|
||||
.distance("10 miles")
|
||||
.location(geoLocation -> geoLocation.latlon(latLonGeoLocation -> latLonGeoLocation.lon(29.88)
|
||||
.lat(31.21)))))
|
||||
.build();
|
||||
log.info("Search request: {}", searchRequest);
|
||||
SearchResponse<Object> search = client.search(searchRequest, Object.class);
|
||||
log.info("Search response: {}", search);
|
||||
List<String> ids = search.hits()
|
||||
.hits()
|
||||
.stream()
|
||||
.map(Hit::id)
|
||||
.toList();
|
||||
assertTrue(ids.contains(lightHouseOfAlexandriaId));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenGeoPointData_whenExecutedGeoPolygonQuery_thenResultNonEmpty() throws Exception {
|
||||
String jsonObject = """
|
||||
{
|
||||
"name":"The Great Rann polygonPoints Kutch",
|
||||
"location":{"lon": 69.859741, "lat": 23.733732}
|
||||
}
|
||||
""";
|
||||
IndexResponse response = client.index(idx -> idx.index(WONDERS_OF_WORLD)
|
||||
.withJson(new StringReader(jsonObject)));
|
||||
String greatRannOfKutchid = response.id();
|
||||
client.indices()
|
||||
.refresh();
|
||||
log.info("Indexed greatRannOfKutchid: {}", greatRannOfKutchid);
|
||||
|
||||
JsonData jsonData = JsonData.fromJson("""
|
||||
{
|
||||
"type":"polygon",
|
||||
"coordinates":[[[68.859,22.733],[68.859,24.733],[70.859,23]]]
|
||||
}
|
||||
""");
|
||||
|
||||
SearchRequest build = new SearchRequest.Builder().query(query -> query.bool(boolQuery -> boolQuery.filter(query1 -> query1.geoShape(geoShapeQuery -> geoShapeQuery.field("location")
|
||||
.shape(geoShapeFieldQuery -> geoShapeFieldQuery.relation(GeoShapeRelation.Within)
|
||||
.shape(jsonData))))))
|
||||
.build();
|
||||
log.info("Search request: {}", build);
|
||||
SearchResponse<Object> search = client.search(build, Object.class);
|
||||
log.info("Search response: {}", search);
|
||||
List<String> searchResults = search.hits()
|
||||
.hits()
|
||||
.stream()
|
||||
.map(Hit::id)
|
||||
.toList();
|
||||
assertTrue(searchResults.contains(greatRannOfKutchid));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void destroy() throws Exception {
|
||||
DeleteIndexRequest deleteIndex = new DeleteIndexRequest(WONDERS_OF_WORLD);
|
||||
client.indices()
|
||||
.delete(deleteIndex, RequestOptions.DEFAULT);
|
||||
.delete(builder -> builder.index(WONDERS_OF_WORLD));
|
||||
}
|
||||
}
|
||||
|
||||
9
pom.xml
9
pom.xml
@@ -370,6 +370,7 @@
|
||||
<module>persistence-modules/spring-data-cassandra-reactive</module> <!--JAVA-21844-->
|
||||
<module>java-nashorn</module>
|
||||
<module>jeromq</module>
|
||||
<module>spring-ejb-modules/ejb-beans</module>
|
||||
</modules>
|
||||
|
||||
</profile>
|
||||
@@ -474,7 +475,6 @@
|
||||
<module>apache-spark</module>
|
||||
|
||||
<module>jenkins-modules</module>
|
||||
<module>jhipster-6</module>
|
||||
<module>jhipster-modules</module>
|
||||
</modules>
|
||||
</profile>
|
||||
@@ -545,6 +545,7 @@
|
||||
<module>persistence-modules/java-cassandra</module> <!-- JAVA-21464 cassandra-unit library doesn't support to run with jdk9 and above -->
|
||||
<module>persistence-modules/spring-data-cassandra-reactive</module> <!--JAVA-21844-->
|
||||
<module>java-nashorn</module>
|
||||
<module>spring-ejb-modules/ejb-beans</module>
|
||||
</modules>
|
||||
|
||||
</profile>
|
||||
@@ -633,7 +634,6 @@
|
||||
<module>apache-spark</module>
|
||||
|
||||
<module>jenkins-modules</module>
|
||||
<module>jhipster-6</module>
|
||||
<module>jhipster-modules</module>
|
||||
</modules>
|
||||
|
||||
@@ -788,6 +788,7 @@
|
||||
<module>guava-modules</module>
|
||||
<module>kubernetes-modules</module>
|
||||
<module>libraries-concurrency</module>
|
||||
<module>jhipster-6</module>
|
||||
<module>libraries-testing</module>
|
||||
<module>maven-modules</module>
|
||||
<module>optaplanner</module>
|
||||
@@ -939,6 +940,7 @@
|
||||
<module>language-interop</module>
|
||||
<module>gradle-modules/gradle/maven-to-gradle</module>
|
||||
<module>persistence-modules/spring-data-neo4j</module>
|
||||
<module>parent-boot-3</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
@@ -1037,6 +1039,7 @@
|
||||
<module>core-groovy-modules</module>
|
||||
|
||||
<module>core-java-modules</module>
|
||||
<module>gcp-firebase</module>
|
||||
<!-- <module>core-java-modules/core-java-9-new-features</module> --> <!-- uses preview features, to be decided how to handle -->
|
||||
<!-- <module>core-java-modules/core-java-12</module> --> <!-- uses preview features, to be decided how to handle -->
|
||||
<!-- <module>core-java-modules/core-java-13</module> --> <!-- uses preview features, to be decided how to handle -->
|
||||
@@ -1059,6 +1062,7 @@
|
||||
<module>guava-modules</module>
|
||||
<module>kubernetes-modules</module>
|
||||
<module>libraries-concurrency</module>
|
||||
<module>jhipster-6</module>
|
||||
<module>libraries-testing</module>
|
||||
<module>maven-modules</module>
|
||||
<module>optaplanner</module>
|
||||
@@ -1226,6 +1230,7 @@
|
||||
<modules>
|
||||
<module>parent-boot-1</module>
|
||||
<module>parent-boot-2</module>
|
||||
<module>parent-boot-3</module>
|
||||
<module>parent-spring-4</module>
|
||||
<module>parent-spring-5</module>
|
||||
<module>parent-spring-6</module>
|
||||
|
||||
@@ -98,6 +98,10 @@
|
||||
<module>spring-boot-properties-3</module>
|
||||
<module>spring-boot-properties-4</module>
|
||||
<module>spring-boot-properties-migrator-demo</module>
|
||||
<module>spring-boot-aws</module>
|
||||
<module>spring-boot-keycloak-adapters</module>
|
||||
<module>spring-boot-mvc-legacy</module>
|
||||
<module>spring-boot-springdoc-2</module>
|
||||
<module>spring-boot-documentation</module>
|
||||
</modules>
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user