I'm migrating MongoDB with Hibernate OGM & ORM to 'pure' Java MongoDB (org.mongodb:mongodb-driver-core:4.4.0.
As: "Hibernate OGM is not going to work with ORM 5.5 (the latest version requires ORM 5.3)".
How to use Hibernate ORM 5.5.x.Final with Jakarta 9 on wildfly-preview-25.0.0.Final
I now want to create a 'dynamic' version say x -> 99 (FindIterable Document). As I did similar with Hibernate OGM & ORM:
if (MotorcycleController.motorcycleManufacturers.length > MotorcyclesEJB.ZERO) {
stringBuilderSQL.append(WHERE);
stringBuilderSQL.append(OPEN_BRACKET);
for (int x = MotorcyclesEJB.ZERO; x < MotorcycleController.motorcycleManufacturers.length; x++) {
stringBuilderSQL.append(MotorcyclesEJB.MANUFACTURER);
stringBuilderSQL.append(MotorcyclesEJB.EQUALS);
stringBuilderSQL.append(MotorcyclesEJB.SINGLE_QUOTE);
stringBuilderSQL.append(MotorcycleController.motorcycleManufacturers[x]);
stringBuilderSQL.append(MotorcyclesEJB.SINGLE_QUOTE);
if ((x + ONE) < MotorcycleController.motorcycleManufacturers.length) {
stringBuilderSQL.append(MotorcyclesEJB.OR);
}
stringBuilderSQL.append(CLOSE_BRACKET);
}
}
I can create (a static) multiple persion of MongoDB 'Collection' using:
FindIterable<Document> motorcycleApriliaMotoGuzzi = mongoCollectionMotorcycleManufacturer.find(or(eq("manufacturer", "Aprilia"), eq("manufacturer", "Moto Guzzi")));
Which can show results (example of one):
INFO [com.gostophandle.ejb.MongoDBEJB] (ServerService Thread Pool -- 97) >>>>> motorcycleApriliaMotoGuzzi = Document{{_id=61d70d6a8c9e88075702af3e, manufacturer=Aprilia, model=RS 660, modelType=E5, typesOf=Sport, dateProductionStarted=Fri Jan 01 00:00:00 GMT 2021, dateProductionEnded=Fri Jan 01 00:00:00 GMT 2021, engine=Document{{type=Four-Stroke, displacement=659.0, cylinder=2.0, capacityUnit=cc, carburation=, bore=0.0, boreMeasurement=mm, stroke=0.0, strokeMeasurement=mm, distribution=, maxiumPowerHp=0.0, maxiumPowerKilowatt=0.0, maxiumPowerRpm=0.0, maximumTorque=0.0, maximumTorqueUnit=Nm, maximumTorqueRpm=0.0}}, performance=Document{{topSpeedMph=105.0, topSpeedKph=0.0, accelleration30Mph=0.0, accelleration60Mph=0.0, accelleration100Mph=0.0, accelleration30Kph=0.0, accelleration60Kph=0.0, accelleration100Kph=0.0}}, dimensionsWeights=Document{{batteryCapacity=, casterAngleDegrees=0.0, dimensionsL=0.0, dimensionsW=0.0, dimensionsH=0.0, frameType=, fuelTankCapacityLitres=0.0, fuelConsumption=0.0, groundClearance=0.0, kerbWeight=0.0, seatHeight=0.0, trail=0.0, wheelbase=0.0}}, chassisBrakesSuspensionWheels=Document{{frame=1, swingarm=2, absSystem=3, frontBrakes=4, rearBrakes=5, frontSuspension=6, rearSuspension=7, tyresFront=8, tyresRear=9, frontTyre=10, rearTyre=11, frontWheel=12, rearWheel=13, instrumentDisplayFunctions=14}}, transmission=Document{{clutch=1, clutchOperation=2, finalDrive=3, gearbox=4, transmissionType=5, primaryReduction=0.0, gearRatios1st=0.0, greaRatios2nd=0.0, gearRatios3rd=0.0, gearRatios4th=0.0, gearRatios5th=0.0, gearRatios6th=0.0}}, instruments=Document{{headlights=1, socket=2, ignitionSystem=3, instruments=4, tailLight=5, usbSocket=6}}, electrics=Document{{}}, colours=[Document{{colour=Acid Gold}}, Document{{colour=Lava Red}}, Document{{colour=Apex Black}}], accessories=[], image=Document{{file=/Users/NOTiFY/IdeaProjects/GoStopHandle/images, url=/Aprilia/2021/, png=ap6115200ebm03-01-m.webp, dimensionsWidth=1500, dimensionsHeight=1000}}}}
I can't get it to create a dynamic version using 'find', 'or' & 'eq' etc.
Any suggestions? TIA.
There are two Filters methods for constructing the Bson for OR:
Filters.or(Bson...)
Filters.or(Iterable<Bson>)
Using the latter, you can construct Bson for each of your conditions that you want to OR together, collect them in a List, and then pass that list to that method to construct the Bson for the OR. I guess this is really an IN operation because these are all the same field but for demonstration purposes:
public Bson or(String field, List<String> values) {
return Filters.or(
values.stream()
.map(v -> Filters.eq(field, v))
.collect(Collectors.toList()));
}
#vsfDawg - Perfect
List<String> stringList = new ArrayList<>();
stringList.add("Aprilia");
stringList.add("Moto Guzzi");
Bson bson = or("manufacturer", stringList);
MongoCursor<Document> cursor = mongoCollectionMotorcycles.find(or("manufacturer", stringList)).iterator();;
try {
while (cursor.hasNext()) {
LOGGER.info(">>>>> 6.4 motorcycleApriliaMotoGuzzi = {}", cursor.next());
}
} finally {
cursor.close();
}
public Bson or(String field, List<String> values) {
return Filters.or(
values.stream()
.map(v -> Filters.eq(field, v))
.collect(Collectors.toList()));
}
}
Displays data:
INFO [com.gostophandle.ejb.MotorcyclesEJB] (default task-1) >>>>> 6.4 motorcycleApriliaMotoGuzzi = Document{{_id=61d70d6a8c9e88075702af3e, manufacturer=Aprilia, model=RS 660, modelType=E5, typesOf=Sport, dateProductionStarted=Fri Jan 01 00:00:00 GMT 2021, dateProductionEnded=Fri Jan 01 00:00:00 GMT 2021, engine=Document{{type=Four-Stroke, displacement=659.0, cylinder=2.0, capacityUnit=cc, carburation=, bore=0.0, boreMeasurement=mm, stroke=0.0, strokeMeasurement=mm, distribution=, maxiumPowerHp=0.0, maxiumPowerKilowatt=0.0, maxiumPowerRpm=0.0, maximumTorque=0.0, maximumTorqueUnit=Nm, maximumTorqueRpm=0.0}}, performance=Document{{topSpeedMph=105.0, topSpeedKph=0.0, accelleration30Mph=0.0, accelleration60Mph=0.0, accelleration100Mph=0.0, accelleration30Kph=0.0, accelleration60Kph=0.0, accelleration100Kph=0.0}}, dimensionsWeights=Document{{batteryCapacity=, casterAngleDegrees=0.0, dimensionsL=0.0, dimensionsW=0.0, dimensionsH=0.0, frameType=, fuelTankCapacityLitres=0.0, fuelConsumption=0.0, groundClearance=0.0, kerbWeight=0.0, seatHeight=0.0, trail=0.0, wheelbase=0.0}}, chassisBrakesSuspensionWheels=Document{{frame=1, swingarm=2, absSystem=3, frontBrakes=4, rearBrakes=5, frontSuspension=6, rearSuspension=7, tyresFront=8, tyresRear=9, frontTyre=10, rearTyre=11, frontWheel=12, rearWheel=13, instrumentDisplayFunctions=14}}, transmission=Document{{clutch=1, clutchOperation=2, finalDrive=3, gearbox=4, transmissionType=5, primaryReduction=0.0, gearRatios1st=0.0, greaRatios2nd=0.0, gearRatios3rd=0.0, gearRatios4th=0.0, gearRatios5th=0.0, gearRatios6th=0.0}}, instruments=Document{{headlights=1, socket=2, ignitionSystem=3, instruments=4, tailLight=5, usbSocket=6}}, electrics=Document{{}}, colours=[Document{{colour=Acid Gold}}, Document{{colour=Lava Red}}, Document{{colour=Apex Black}}], accessories=[], image=Document{{file=/Users/NOTiFY/IdeaProjects/GoStopHandle/images, url=/Aprilia/2021/, png=ap6115200ebm03-01-m.webp, dimensionsWidth=1500, dimensionsHeight=1000}}}}
12:42:59,335 INFO [com.gostophandle.ejb.MotorcyclesEJB] (default task-1) >>>>> 6.4 motorcycleApriliaMotoGuzzi = Document{{_id=61d70d6a8c9e88075702af58, manufacturer=Moto Guzzi, model=Le Mans, modelType=I, typesOf=Sport, dateProductionStarted=Thu Jan 01 00:00:00 GMT 1976, dateProductionEnded=Sat Jan 01 00:00:00 GMT 1977, engine=Document{{type=Four-Stroke, displacement=850.0, cylinder=2.0, capacityUnit=cc, carburation=null, bore=80.0, boreMeasurement=mm, stroke=74.0, strokeMeasurement=mm, distribution=null, maxiumPowerHp=85.0, maxiumPowerKilowatt=38.0, maxiumPowerRpm=6200.0, maximumTorque=60.0, maximumTorqueUnit=Nm, maximumTorqueRpm=4900.0}}, electrics=Document{{}}, colours=[Document{{colour=Red}}, Document{{colour=Silver Blue}}], accessories=[Document{{productNumber=MG0123456789, productName=Product 1}}, Document{{productNumber=MG0123456789, productName=Product 2}}], image=Document{{file=/Users/NOTiFY/IdeaProjects/GoStopHandle/images, url=/MotoGuzzi/1976/, png=motorcycle.png, dimensionsWidth=900, dimensionsHeight=440}}}}
I need to obtain the master public DNS value via the Java SDK. The only information that I'll have at the start of the application is the ClusterName which is static.
Thus far I've been able to pull out all the other information that I need excluding this and this, unfortunately is vital for the application to be a success.
This is the code that I'm currently working with:
List<ClusterSummary> summaries = clusters.getClusters();
for (ClusterSummary cs: summaries) {
if (cs.getName().equals("test") && WHITELIST.contains(cs.getStatus().getState())) {
ListInstancesResult instances = emr.listInstances(new ListInstancesRequest().withClusterId(cs.getId()));
clusterHostName = instances.getInstances().get(0).toString();
jobFlowId = cs.getId();
}
}
I've removed the get for PublicIpAddress as wanted the full toString for testing. I should be clear in that this method does give me the DNS that I need but I have no way of differentiating between them.
If my EMR has 4 machines, I don't know which position in the list that Instance will be. For my basic trial I've only got two machines, 1 master and a worker. .get(0) has returned both the values for master and the worker on successive runs.
The information that I'm able to obtain from these is below - my only option that I can see at the moment is to use the 'ReadyDateTime' as an identifier as the master 'should' always be ready first, but this feels hacky and I was hoping on a cleaner solution.
{Id: id,
Ec2InstanceId: id,
PublicDnsName: ec2-54--143.compute-1.amazonaws.com,
PublicIpAddress: 54..143,
PrivateDnsName: ip-10--158.ec2.internal,
PrivateIpAddress: 10..158,
Status: {State: RUNNING,StateChangeReason: {},
Timeline: {CreationDateTime: Tue Feb 21 09:18:08 GMT 2017,
ReadyDateTime: Tue Feb 21 09:25:11 GMT 2017,}},
InstanceGroupId: id,
EbsVolumes: []}
{Id: id,
Ec2InstanceId: id,
PublicDnsName: ec2-54--33.compute-1.amazonaws.com,
PublicIpAddress: 54..33,
PrivateDnsName: ip-10--95.ec2.internal,
PrivateIpAddress: 10..95,
Status: {State: RUNNING,StateChangeReason: {},
Timeline: {CreationDateTime: Tue Feb 21 09:18:08 GMT 2017,
ReadyDateTime: Tue Feb 21 09:22:48 GMT 2017,}},
InstanceGroupId: id
EbsVolumes: []}
Don't use ListInstances. Instead, use DescribeCluster, which returns as one of the fields MasterPublicDnsName.
To expand on what was mentioned by Jonathon:
AmazonEC2Client ec2 = new AmazonEC2Client(cred);
DescribeInstancesResult describeInstancesResult = ec2.describeInstances(new DescribeInstancesRequest().withInstanceIds(clusterInstanceIds));
List<Reservation> reservations = describeInstancesResult.getReservations();
for (Reservation res : reservations) {
for (GroupIdentifier group : res.getGroups()) {
if (group.getGroupName().equals("ElasticMapReduce-master")) { // yaaaaaaaaah, Wahay!
masterDNS = res.getInstances().get(0).getPublicDnsName();
}
}
}
AWSCredentials credentials_profile = null;
credentials_profile = new
DefaultAWSCredentialsProviderChain().getCredentials();
AmazonElasticMapReduceClient emr = new
AmazonElasticMapReduceClient(credentials_profile);
Region euWest1 = Region.getRegion(Regions.US_EAST_1);
emr.setRegion(euWest1);
DescribeClusterFunction fun = new DescribeClusterFunction(emr);
DescribeClusterResult res = fun.apply(new
DescribeClusterRequest().withClusterId(clusterId));
String publicDNSName =res.getCluster().getMasterPublicDnsName();
Below is the working code to get the public DNS name.
I have simple test
#SuppressWarnings("deprecation")
#Test
public void test_NO_MILLIS() throws ParseException {
String rabbit = "22-OCT-15 06.37.35";
final String PATTERN = "dd-MMM-yy HH.mm.ss";
Date dateObject = new SimpleDateFormat(PATTERN).parse(rabbit);
Assert.assertNotNull(dateObject);
Assert.assertEquals(22, dateObject.getDate());
Assert.assertEquals(10, dateObject.getMonth() + 1);
Assert.assertEquals(2015, dateObject.getYear() + 1900);
Assert.assertEquals(6, dateObject.getHours());
Assert.assertEquals(37, dateObject.getMinutes());
Assert.assertEquals(35, dateObject.getSeconds());
}
And everything goes right. I get 22 as day in result.
But after I am adding microseconds both to pattern and to string value to be parsed
#Test
public void test_MILLIS() throws ParseException {
String rabbit = "22-OCT-15 06.37.35.586173000";
final String PATTERN = "dd-MMM-yy HH.mm.ss.SSSSSSSSS";
Date dateObject = new SimpleDateFormat(PATTERN).parse(rabbit);
Assert.assertNotNull(dateObject);
Assert.assertEquals(22, dateObject.getDate());
Assert.assertEquals(10, dateObject.getMonth() + 1);
Assert.assertEquals(2015, dateObject.getYear() + 1900);
Assert.assertEquals(6, dateObject.getHours());
Assert.assertEquals(37, dateObject.getMinutes());
Assert.assertEquals(35, dateObject.getSeconds());
}
I get an assert failure
junit.framework.AssertionFailedError: expected:<22> but was:<29>
at junit.framework.Assert.fail(Assert.java:57)
at junit.framework.Assert.failNotEquals(Assert.java:329)
at junit.framework.Assert.assertEquals(Assert.java:78)
at junit.framework.Assert.assertEquals(Assert.java:234)
at junit.framework.Assert.assertEquals(Assert.java:241)
at main.TestDateFormatTest.test_MILLIS(TestDateFormatTest.java:36)
...
Which means that day has become 29 instead of 22. What has gone wrong?
Tested
Platforms: mac osx 10.9, ubuntu, win7
jdk: 7,6
The format pattern S for milliseconds doesn't take into account mathematical placement values; it just sees 586173000 as the number of milliseconds to add to the rest of the date. That number is equivalent to about 6.784 days, so that explains why the date became 29 instead of 22.
Before parsing, cut off the milliseconds at 3 digits, e.g. "22-OCT-15 06.37.35.586", so it's interpreted as 586 milliseconds.
I am reading this topic about java Thread.
And there is an example:
import java.util.Vector;
class Producer extends Thread {
static final int MAXQUEUE = 5;
private Vector messages = new Vector();
#Override
public void run() {
try {
while (true) {
putMessage();
//sleep(5000);
}
} catch (InterruptedException e) {
}
}
private synchronized void putMessage() throws InterruptedException {
while (messages.size() == MAXQUEUE) {
wait();
}
messages.addElement(new java.util.Date().toString());
System.out.println("put message");
notify();
//Later, when the necessary event happens, the thread that is running it calls notify() from a block synchronized on the same object.
}
// Called by Consumer
public synchronized String getMessage() throws InterruptedException {
notify();
while (messages.size() == 0) {
wait();//By executing wait() from a synchronized block, a thread gives up its hold on the lock and goes to sleep.
}
String message = (String) messages.firstElement();
messages.removeElement(message);
return message;
}
}
class Consumer extends Thread {
Producer producer;
Consumer(Producer p) {
producer = p;
}
#Override
public void run() {
try {
while (true) {
String message = producer.getMessage();
System.out.println("Got message: " + message);
//sleep(200);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
Producer producer = new Producer();
producer.start();
new Consumer(producer).start();
}
}
And the author said:
A possible output sequence:
Got message: Fri Dec 02 21:37:21 EST 2011
put message
put message
put message
put message
put message
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
put message
put message
put message
put message
put message
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
But when I run this code I got this result:
put message
put message
put message
put message
put message
put message
Got message: Tue Sep 24 16:44:59 CST 2013
Got message: Tue Sep 24 16:45:00 CST 2013
put message
Got message: Tue Sep 24 16:45:00 CST 2013
put message
Got message: Tue Sep 24 16:45:00 CST 2013
put message
..............
What is the problem?
Any one can explain it for me?
The author's entire point is that the order of tasks between different threads is unpredictable. He printed a possible output sequence, but many, many others are possible.
In addition to the already explained output I must add that the book you are reading doesn't seem to be a very good source to learn from. It teaches to:
extend Thread, a notorious bad practice;
invoke wait and notify on a Thread instance—another known, documented bad practice.
use the wait and notify mechanism in the first place, which has mostly been superseded by much more convenient and simpler java.util.concurrent tools such as CountDownLatch, Semaphore, and Phaser.
Your version of output is correct. Because "Got Message" is not possible without "put message". I mean, if there is no message in queue then how can you retrieve the message. Developer in his example might have given sample output which was not actual code run output but self made just for example.
Remember :
[Count of total "Got message" till particular line] will always be <= [Count of total "put message" till that very line]
The only strange thing is that there are 6 consecutive "put message" which seems to be impossible because the maximum queue size is 5.
But this is because the code sequence
producer.getMessage()
System.out.println("Got message: " + message);
is - of course - not atomic and has been interrupted by a thread switch.
By the way - always use notifyAll() instead of notify.