I have a collection name Order with many properties. I wanna create a materialized view with 3 fields from Order to destStationList. I'm using the following java method to do that.
private void createMaterializedView() {
String collectionName = "orders";
String viewName = "destStationList";
// Attempt to create the view
if(mongoTemplate.collectionExists(viewName)){
mongoTemplate.dropCollection(viewName);
}
CommandResult result = mongoTemplate.executeCommand("{" +
"aggregate: '" + viewName + "', " +
"pipeline: [ { $project: { travelDate: 1, trainNumber: 1, to: 1 } }, { $merge: { into: \"destStationList\", whenMatched: \"replace\", whenNotMatched: \"insert\" } } ]," +
"cursor: { }"+
"}");
if(result.ok()) {
LOGGER.info("Successfully created view '{}' on collection '{}'", viewName, collectionName);
}
else {
System.out.println("Failed to create view '" + viewName + "' on collection '" + collectionName + "' - " + result.getErrorMessage());
}
}
I have tested the following mongo shell command to check that in my local mongodb. It works well.
db.runCommand( {
aggregate: "order",
pipeline: [ { $project: { travelDate: 1, trainNumber: 1, to: 1 } }, { $merge: { into: "destStationList", whenMatched: "replace", whenNotMatched: "insert" } } ],
cursor: { }
} );
For your information, I'm using MongoDB version 4.4.
The problem is that executing the java method shows that the view is created successfully. But when I run the command mongoTemplate.collectionExists("destStationList") it returns false and also cannot retrieve data by querying from the view.
Can anyone please help me with it? How can I create a mongo materialized view using java?
Should it be collectionName instead of viewName in the aggregate?
CommandResult result = mongoTemplate.executeCommand("{" +
"aggregate: '" + collectionName + "', " +
"pipeline: [ { $project: { travelDate: 1, trainNumber: 1, to: 1 } }, { $merge: { into: \"destStationList\", whenMatched: \"replace\", whenNotMatched: \"insert\" } } ]," +
"cursor: { }"+
"}");
You may also want to use the viewName variable rather than hardcode it into the String.
I am (being an absolute beginner), trying to create a simple tool, that creates some objects and links them.
The objects are:
Customers
Licenses (2 types, extends class)
The idea is to use (one of) the customer company name when creating a license, so the license is linked to a customer.
I use ArrayLists to store the data.
I tried to use the getter for Customer cCompany, but when I try to actually create a new license object, I get errors about incompatible types (String to object of type customer)
How can I fix that error?
Any help is highly appreciated, but please explain well, me being an absolute beginner. I probably overcomplicate stuff....
Some code extracts:
From Main:
public class Main {
public static void main(String[] args) {
//Create customers
List <Customer> customers = new ArrayList <> (10);
customers.add(new Customer("TestCompany","John Doe",1234567890,"John#testcompany.com"));
....
//Create Elvis licenses (based on superclass License)
List <ElvisLicense> ellicenses = new ArrayList <> (10);
ellicenses.add(new ElvisLicense("TestCompany","VendorA",1234,"1234-A","Solutions Server gold","1234-dtbk-87654-nlof",10, true , true));
Class: Customer:
class Customer {
String cCompany;
private String cName;
private int cPhone;
private String cEmail;
public Customer( String cCompany, String cName,int cPhone, String cEmail)
{
this.cCompany = cCompany;
this.cName = cName;
this.cPhone = cPhone;
this.cEmail = cEmail;
}
//This getter should be used to link the license to the customer (Done in License.java)
public String getcCompany() {
return cCompany;
}
Class License (Superclass)
class License {
// Used no modifier to set access for Class/Package and Subclass inside the package
Customer licenseCompany;
String lVendor;
int lContractNumber;
String lCertificateNumber;
String lProductName;
String lLicenseKey;
int lNumberOfSeats;
public License(Customer cCompany, String lVendor, int lContractNumber, String lCertificateNumber,
String lProductName, String lLicenseKey, int lNumberOfSeats)
{
licenseCompany = cCompany;
this.lVendor = lVendor;
this.lVendor = lVendor;
this.lContractNumber = lContractNumber;
this.lCertificateNumber = lCertificateNumber;
this.lProductName = lProductName;
this.lLicenseKey = lLicenseKey;
this.lNumberOfSeats = lNumberOfSeats;
}
public Customer getLicenseCompany() {
return licenseCompany;
}
public void setLicenseCompany(Customer licenseCompany) {
this.licenseCompany = licenseCompany;
}
//preparations to allow for example printing the content of an arraylist element
#Override
public String toString(){
return "Customer name " + getLicenseCompany() + "\n" + "Vendor name " + getlVendor() + "\n" + "Contract number: " + getlContractNumber() + "\n"
+ "Certificate number: " + getlCertificateNumber() + "\n" +
"Product name " + getlProductName() + "\n" + "Licence key: " + getlLicenseKey() + "\n"
+ "Number of seats: " + getlNumberOfSeats();
}
}
And the extended class:
public class ElvisLicense extends License{
private boolean elIsBundle;
private boolean elIsSubscription;
public ElvisLicense(
Customer licenseCompany,
String lVendor,
int lContractNumber,
String lCertificateNumber,
String lProductName,
String lLicenseKey,
int lNumberOfSeats,
boolean elIsBundle,
boolean elIsSubscription
)
{
super(
licenseCompany,
lVendor,
lContractNumber,
lCertificateNumber,
lProductName,
lLicenseKey,
lNumberOfSeats);
this.elIsBundle = elIsBundle;
this.elIsSubscription = elIsSubscription;
}
.....
#Override
public String toString(){
return "Customer name " + licenseCompany + "\n"
+ "Vendor name " + lVendor + "\n"
+ "Contract number: " + lContractNumber + "\n"
+ "Certificate number: " + lCertificateNumber + "\n"
+ "Product name " + lProductName + "\n"
+ "Licence key: " + lLicenseKey + "\n"
+ "Number of seats: " + lNumberOfSeats + "\n"
+ "Number of seats: " + elIsBundle + "\n"
+ "Number of seats: " + elIsSubscription;
}
}
I expect that the Customername is used when creating a new license.
Below line is wrong.
ellicenses.add(new ElvisLicense("TestCompany","VendorA",1234,"1234-A","Solutions Server gold","1234-dtbk-87654-nlof",10, true , true));
As license need customer object an parameter. Instead, you should create customer object first.
ellicenses.add(new ElvisLicense(new Customer("TestCompany","VendorA",1234,"1234-A"),"Solutions Server gold","1234-dtbk-87654-nlof",10, true , true));
for reusing that customer list to avoid create company.
for(Customer customer : customers){
// here you need some way to offer other parameters except customer parameter.
License license = new new ElvisLicense(customer,"Solutions Server gold","1234-dtbk-87654-nlof",10, true , true);
ellicenses.add(license);
}
What you need to do is to use one of the Customer objects you have already created when creating the ElvisLicense object. To more easily find that customer by name I suggest you store them in a map instead of a list with the name as a key.
Map<String, Customer> customerMap = new HashMap<>();
Customer customer = new Customer("TestCompany","John Doe",1234567890,"John#testcompany.com"));
customerMap.put(customer.getcCompany(), customer);
so when creating the license you look up the customer
List <ElvisLicense> ellicenses = new ArrayList <> (10);
Customer customer = customerMap.get("TestCompany");
if (customer != null) {
ElvisLicense license = new ElvisLicense(customer,"VendorA",1234,"1234-A","Solutions Server gold","1234-dtbk-87654-nlof",10, true , true));
ellicenses.add(license);
} else {
//If the customer isn't found you need some kind of error handling, better than below :)
System.out.println("Can't create a license, no customer found");
}
I have Service which will give us response back by querying MongoDB on the basis of some parameter provided
#RequestMapping(value = "/custRef/{custRef}", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<String> getServiceId(#PathVariable("custRef") String custRef) throws InterruptedException {
System.out.println("Thread.currentThread().getName() :"+Thread.currentThread().getName());
String serviceId=//calling Mongo Service and getting the result
if(custRef == null) {
return new ResponseEntity<String>("No service id available for the given FO Id:" + custRef,HttpStatus.NOT_FOUND);
}
return new ResponseEntity<String>(serviceId,HttpStatus.OK);
}
I have another client which will call the above service by providing the proper parameter. I want to call the above service by using 10 threads. can I get the response back in same frequency from the above service or do I need to do any configuration on the server where above one is running
ExecutorService es = Executors.newFixedThreadPool(50);
for (RouterInfo router : listOfcpeRouterInfo){
Future<String> serviceIDS = es.submit(new CalculationTaskA(router.getCustomerRef(), rieClient));
}
#Override
public String call() throws Exception {
String currentThreadName = Thread.currentThread().getName();
log.info("##### [" + currentThreadName + "] <" + taskId + "> STARTIING #####");
// System.out.println("[" + currentThreadName + "] <" + taskId + ">
// Sleeping for " + sleepTime + " millis");
// TimeUnit.MILLISECONDS.sleep(sleepTime);
//
String serviceId = null;
try {
///
serviceId = rieClient.getObject(customerRef);
log.info("serviceId for given foid: " + customerRef + " is " + serviceId);
} catch (ParseException pe) {
log.error("error while parsing Data", pe);
}
log.info("****** [" + currentThreadName + "] <" + taskId + "> DONE ******");
return serviceId;
}
calling above service
enter code here
Inside getObject I am doing below
ResponseEntity<String> response=restTemplate.exchange(this.serviceIdUrl+"/{foId}",HttpMethod.GET,entity,String.class,foId);
By default, Spring Boot applications are multithreaded so your code sample
ExecutorService es = Executors.newFixedThreadPool(50);
for (RouterInfo router : listOfcpeRouterInfo){ Future serviceIDS = es.submit(new CalculationTaskA(router.getCustomerRef(), rieClient)); }
would only be needed in your "Mongo" Service if asynchronous calls are to be made by the "Mongo" service.
So I have a plugin im making where they get kicked with a message. I want that message to be in color that is set in the config.yml. heres my code:
}
if (l == 2) {
settings.getData().set("" + target.getName() + "", null);
settings.saveData();
target.kickPlayer(this.getConfig().getString("BanMessage"));
target.setBanned(true);
Bukkit.getServer().broadcastMessage(ChatColor.RED + target.getName() + " " + "Has been tempbanned for 25 Minutes by " + sender.getName() + "" + "(3/3)");
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
public void run() {
target.setBanned(false);
}
}, 1500 * 20);
return true;
}
Heres my config.yml:
BanMessage: You have been temp banned for 25 Minutes
You could use ChatColor.translateAlternateColorCodes():
String kickMessage = plugin.getConfig().getString("BanMessage");
kickMessage = ChatColor.translateAlternateColorCodes('&', kickMessage);
target.kickPlayer(kickMessage);
target.setBanned(true);
You can use these color codes in your configuration file.
So, putting in &6You have been banned for &4Spamming Will give you ChatColor.GOLD + "You have been banned for " + ChatColor.DARK_RED + " Spamming"
and if you would like to make it so they get that same message whenever they join if they're banned, you can use:
#EventHandler
public void playerJoin(PlayerJoinEvent e){
if(myMethodToCheckIfAPlayerIsTempBanned(e.getPlayer()){
String msg = myMethodToGetPlayersBanMessage(e.getPlayer());
e.getPlayer().kickPlayer(msg);
}
}
This should work:
String kickMessage = this.getConfig().getString("BanMessage");
kickMessage.replaceAll("(?i)&([a-f0-9])", "\u00A7$1");
target.kickPlayer(kickMessage);
target.setBanned(true);
Then, you should be able to use these color codes in your config.
ex.
BanMessage: &3You &0have been banned &1for &425 &3minutes
will display as
You have been temp banned for 25 Minutes
I have a xml file where there are multiple arrays in the root element. Whenever am trying to use the implicitcollection declaration, the xstream is only processing the last declaration and everything else remains null. In the below code the first array ERRORS remains null whereas DEBITS is parsed.
public class XMLParser {
/**
* #param args
* #throws Exception
*/
public static void main(String[] args){
String xmlString = "<DebitsWSDS xmlns=\"\"> " +
" <DEBITS> " +
" <DEBIT_ID>-1</DEBIT_ID> " +
" </DEBITS> " +
" <DEBITS> " +
" <DEBIT_ID>-2</DEBIT_ID> " +
" </DEBITS> " +
" <ERRORS> " +
" <ERROR_ID>1</ERROR_ID> " +
" </ERRORS> " +
" <ERRORS> " +
" <ERROR_ID>2</ERROR_ID> " +
" </ERRORS> " +
"</DebitsWSDS> ";
DebitsWSDS debitsWSDS;
try {
debitsWSDS = convertFeesSetXMLResultToDebitsWSDS(xmlString);
System.out.println(debitsWSDS.ERRORS==null);
System.out.println(debitsWSDS.DEBITS==null);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static DebitsWSDS convertFeesSetXMLResultToDebitsWSDS(String xml) throws Exception{
XStream xstream = new XStream(new StaxDriver());
xstream.alias("DebitsWSDS", DebitsWSDS.class);
xstream.addImplicitCollection(DebitsWSDS.class, "DEBITS");
xstream.addImplicitCollection(DebitsWSDS.class, "ERRORS");
xstream.alias("ERROR_ID", String.class);
//System.out.println(xml);
DebitsWSDS debitsWSDS =(DebitsWSDS)xstream.fromXML(xml);
return debitsWSDS;
}
}
public class DebitsWSDS {
public List<ERROR> ERRORS;
public List<DEBIT> DEBITS;
public class ERROR {
public String ERROR_ID;
}
public class DEBIT {
public String DEBIT_ID;
}
}
I'm not quite sure what you'd expect it to do. XStream is a bean/XML mapping tool, and you effectively have two XML lists mapped to the same List element in your bean. If you really want that XML strucutre I would construct your bean using a SAX parser or similar, create an empty list and let the parser callbacks add to that list.