translate SQL join to JPQL - jpa

Currently, all articles in the join for the JPQL query are returned in the getRangeOfArticles method, whereas only a range of articles should get returned.
The MySQL console output I'm after, but would like to implement in JPQL:
mysql>
mysql> SELECT * FROM articles LEFT OUTER JOIN newsgroups ON articles.NEWSGROUP_ID=newsgroups.ID WHERE newsgroups.NEWSGROUP = "gwene.com.economist" AND articles.ID BETWEEN 450 AND 453;
+-----+---------------+--------------+------+---------------------+
| ID | MESSAGENUMBER | NEWSGROUP_ID | ID | NEWSGROUP |
+-----+---------------+--------------+------+---------------------+
| 450 | 554 | 5 | 5 | gwene.com.economist |
| 451 | 555 | 5 | 5 | gwene.com.economist |
| 452 | 556 | 5 | 5 | gwene.com.economist |
| 453 | 557 | 5 | 5 | gwene.com.economist |
+-----+---------------+--------------+------+---------------------+
4 rows in set (0.02 sec)
mysql>
mysql> show tables;
+------------------+
| Tables_in_usenet |
+------------------+
| articles |
| newsgroups |
+------------------+
2 rows in set (0.01 sec)
mysql> describe articles;
+---------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| MESSAGENUMBER | int(11) | YES | | NULL | |
| NEWSGROUP_ID | bigint(20) | YES | MUL | NULL | |
+---------------+------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> describe newsgroups;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| NEWSGROUP | varchar(255) | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql>
I'm trying to replicate that SQL query in JPQL in the getRangeOfArticles method:
package net.bounceme.dur.usenet.driver;
import java.util.List;
import java.util.logging.Logger;
import javax.mail.Folder;
import javax.mail.Message;
import javax.persistence.*;
import net.bounceme.dur.usenet.model.Article;
import net.bounceme.dur.usenet.model.Newsgroup;
class DatabaseUtils {
private static final Logger LOG = Logger.getLogger(DatabaseUtils.class.getName());
private EntityManagerFactory emf = Persistence.createEntityManagerFactory("USENETPU");
private EntityManager em = emf.createEntityManager();
//SELECT MAX(MESSAGENUMBER) FROM articles LEFT OUTER JOIN newsgroups ON articles.NEWSGROUP_ID=newsgroups.ID WHERE newsgroups.NEWSGROUP = "gwene.com.economist";
public int getMaxMessageNumber(Folder folder) {
int maxMessageNumber = 0;
String newsgroup = folder.getFullName();
String queryString = "select max(article.messageNumber) from Article article left join article.newsgroup newsgroup where newsgroup.newsgroup = '" + newsgroup + "'";
try {
maxMessageNumber = (Integer) em.createQuery(queryString).getSingleResult();
} catch (Exception e) {
LOG.severe("setting max to zero for " + newsgroup);
}
LOG.fine(folder.getFullName() + "\t" + maxMessageNumber);
return maxMessageNumber;
}
//SELECT * FROM articles LEFT OUTER JOIN newsgroups ON articles.NEWSGROUP_ID=newsgroups.ID WHERE newsgroups.NEWSGROUP = "gwene.com.economist" AND articles.ID BETWEEN 450 AND 500;
public List<Article> getRangeOfArticles(Page page) {
String fullNewsgroupName = page.getFolder().getFullName();
int minRange = page.getMin();
int maxRange = page.getMax();
String queryString = "select article from Article article left join article.newsgroup newsgroup where newsgroup.newsgroup = :newsGroupParam";
TypedQuery<Article> query = em.createQuery(queryString, Article.class);
query.setParameter("newsGroupParam", fullNewsgroupName);
List<Article> results = query.getResultList();
LOG.info(results.toString());
return results;
}
public void persistArticle(Message message, Folder folder) {
em.getTransaction().begin();
String fullNewsgroupName = folder.getFullName();
Newsgroup newsgroup = null;
TypedQuery<Newsgroup> query = em.createQuery("SELECT n FROM Newsgroup n WHERE n.newsgroup = :newsGroupParam", Newsgroup.class);
query.setParameter("newsGroupParam", fullNewsgroupName);
try {
newsgroup = query.getSingleResult();
LOG.fine("found " + query.getSingleResult());
} catch (javax.persistence.NoResultException e) {
LOG.fine(e + "\ncould not find " + fullNewsgroupName);
newsgroup = new Newsgroup(folder);
em.persist(newsgroup);
} catch (NonUniqueResultException e) {
LOG.warning("\nshould never happen\t" + fullNewsgroupName);
} /*
* finally { if (em.getTransaction().isActive()) {
* em.getTransaction().rollback(); }
*/
Article article = new Article(message, newsgroup);
em.persist(article);
em.getTransaction().commit();
}
public void close() {
em.close();
emf.close();//necessary?
}
}

If you want to query a collection of Articles by their Newsgroup's name you can do something like this:
String queryString = "select a from Article a where a.newsgroup.newsgroup = :newsGroupParam";
TypedQuery<Article> query = em.createQuery(queryString, Article.class);
query.setParameter("newsGroupParam", fullNewsgroupName);
List<Article> results = query.getResultList();
Don't write joins in JPQL, let JPA do the work for you.
As an extra tip, you should always write your queries like this to prevent SQL injection.
public int getMaxMessageNumber(Folder folder) {
int maxMessageNumber = 0;
String queryString = "select max(a.messageNumber) from Article a where a.newsgroup.newsgroup = :newsgroup";
Query q = em.createQuery(queryString);
q.setParameter("newsgroup", folder.getFullName());
try {
maxMessageNumber = (Integer) q.getSingleResult();
} catch (Exception e) {
LOG.severe("setting max to zero for " + newsgroup);
}
LOG.fine(folder.getFullName() + "\t" + maxMessageNumber);
return maxMessageNumber;
}

Just in terms of the query, I believe it's String queryString = "select article from Article article left join article.newsgroup newsgroup where newsgroup.newsgroup = :newsGroupParam and article.messageNumber between 100 and 500"; although I need to add some parameters in there for ranges. See getRangeOfArticles below:
package net.bounceme.dur.usenet.driver;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.persistence.*;
import net.bounceme.dur.usenet.model.Article;
import net.bounceme.dur.usenet.model.Newsgroup;
import net.bounceme.dur.usenet.model.Usenet;
class DatabaseUtils {
private static final Logger LOG = Logger.getLogger(DatabaseUtils.class.getName());
private EntityManagerFactory emf = Persistence.createEntityManagerFactory("USENETPU");
private EntityManager em = emf.createEntityManager();
//SELECT MAX(MESSAGENUMBER) FROM articles LEFT OUTER JOIN newsgroups ON articles.NEWSGROUP_ID=newsgroups.ID WHERE newsgroups.NEWSGROUP = "gwene.com.economist";
public int getMaxMessageNumber(Folder folder) {
int maxMessageNumber = 0;
String newsgroup = folder.getFullName();
String queryString = "select max(article.messageNumber) from Article article left join article.newsgroup newsgroup where newsgroup.newsgroup = '" + newsgroup + "'";
try {
maxMessageNumber = (Integer) em.createQuery(queryString).getSingleResult();
} catch (Exception e) {
LOG.severe("setting max to zero for " + newsgroup);
}
LOG.fine(folder.getFullName() + "\t" + maxMessageNumber);
return maxMessageNumber;
}
//SELECT * FROM articles LEFT OUTER JOIN newsgroups ON articles.NEWSGROUP_ID=newsgroups.ID WHERE newsgroups.NEWSGROUP = "gwene.com.economist" AND articles.ID BETWEEN 450 AND 500;
public List<Article> getRangeOfArticles(Page page) {
String fullNewsgroupName = page.getFolder().getFullName();
int minRange = page.getMin();
int maxRange = page.getMax();
String queryString = "select article from Article article left join article.newsgroup newsgroup where newsgroup.newsgroup = :newsGroupParam and article.messageNumber between 100 and 500";
TypedQuery<Article> query = em.createQuery(queryString, Article.class);
query.setParameter("newsGroupParam", fullNewsgroupName);
List<Article> articles = query.getResultList();
Usenet usenet = Usenet.INSTANCE;
for (Article article : articles) {
List<String> string = new ArrayList<>();
string.add(article.getId().toString());
string.add(Long.toString(article.getMessageNumber()));
Message message = usenet.getMessage(page.getFolder(), article.getMessageNumber());
try {
string.add(message.getSubject());
} catch (MessagingException ex) {
Logger.getLogger(DatabaseUtils.class.getName()).log(Level.SEVERE, null, ex);
}
Newsgroup n = article.getNewsgroup();
string.add(n.getNewsgroup());
LOG.info(string.toString());
}
return articles;
}
public void persistArticle(Message message, Folder folder) {
em.getTransaction().begin();
String fullNewsgroupName = folder.getFullName();
Newsgroup newsgroup = null;
TypedQuery<Newsgroup> query = em.createQuery("SELECT n FROM Newsgroup n WHERE n.newsgroup = :newsGroupParam", Newsgroup.class);
query.setParameter("newsGroupParam", fullNewsgroupName);
try {
newsgroup = query.getSingleResult();
LOG.fine("found " + query.getSingleResult());
} catch (javax.persistence.NoResultException e) {
LOG.fine(e + "\ncould not find " + fullNewsgroupName);
newsgroup = new Newsgroup(folder);
em.persist(newsgroup);
} catch (NonUniqueResultException e) {
LOG.warning("\nshould never happen\t" + fullNewsgroupName);
} /*
* finally { if (em.getTransaction().isActive()) {
* em.getTransaction().rollback(); }
*/
Article article = new Article(message, newsgroup);
em.persist(article);
em.getTransaction().commit();
}
public void close() {
em.close();
emf.close();//necessary?
}
}
However, I seem to get some errors:
Aug 06, 2012 12:00:02 AM net.bounceme.dur.usenet.model.Usenet getMessage
SEVERE: null
javax.mail.MessageRemovedException: No such article: 273
so perhaps there's an error with the query syntax or meaning, or I have a logical error.

Related

JPA Native Query across multiple tables

I have the following defined as a native query in a repository (dispenseRepository) :
#Query(
value = "SELECT p.*, c.*, s.*, d.* from patient p, consult c ,script s,dispense d "
+ " where p.patient_id=c.patient_id "
+ " and c.consult_id = d.consult_id "
+ " and c.fk_script_id =s.script_id"
+ " and c.consult_id=?1 ",
nativeQuery = true
)
List<Dispense> findInvoiceByConsultId(Long consultId);
The Rest Controller has :
#RequestMapping(value = "/api/invoice/{consultId}",method = {RequestMethod.GET})
public List<Dispense> invoice(#PathVariable(value="consultId")Long consultId){
return dispenseRepository.findInvoiceByConsultId(consultId);
}
When I hit the api I only get dispense details:
[
{
"dispenseId": 1,
"icd10": "J.10",
"tariffCode": "10010",
"dispenseItem": "Lenses",
"price": 400.0
},
{
"dispenseId": 3,
"icd10": "J.10",
"tariffCode": "111000",
"dispenseItem": "Other",
"price": 1500.0
},
{
"dispenseId": 4,
"icd10": "K.100",
"tariffCode": "10010",
"dispenseItem": "Eye Test",
"price": 550.0
}
]
I'd like all the data as per query which will be used for Jasper report
patient-consult 1-M
consult-script 1-1
consult-dispense 1-M
Since in your query you return all fields from all tables: SELECT p.*, c.*, s.*, d.* from patient p, consult c ,script s,dispense d creating projections/DTOs for so many objects and fields is very cumbersome. There are 2 ways to proceed. Either specify exactly the fields you want from each table in your query and create a DTO to hold those fields.
e.g.
Approach 1:
I chose only one field from each table to make it as example. Please not that you have to convert your query from native to jpa one!
#Query("SELECT new com.example.demo.ResultDTO(p.patientName, c.reservationNumber, s.addition, d.dispenseItem) from Patient p, Consult c, Script s, Dispense d ...")
List<ResultDTO> findInvoiceByConsultId(Long consultId);
and ResultDTO class can be:
package com.example.demo;
public class ResultDTO {
private String patientName;
private String reservationNumber;
private String addition;
private String dispenseItem;
public ResultDTO(String patientName, String reservationNumber, String addition, String dispenseItem) {
this.patientName = patientName;
this.reservationNumber = reservationNumber;
this.addition = addition;
this.dispenseItem = dispenseItem;
}
public String getPatientName() {
return patientName;
}
public void setPatientName(String patientName) {
this.patientName = patientName;
}
public String getReservationNumber() {
return reservationNumber;
}
public void setReservationNumber(String reservationNumber) {
this.reservationNumber = reservationNumber;
}
public String getAddition() {
return addition;
}
public void setAddition(String addition) {
this.addition = addition;
}
public String getDispenseItem() {
return dispenseItem;
}
public void setDispenseItem(String dispenseItem) {
this.dispenseItem = dispenseItem;
}
}
UPDATE
Approach 1 won't work with a nativeQuery, you have to convert it to jpa one so unless you convert your query to jpql, the above code wont work.
OR the much easier but bulkier, keep the query as is and place the result on a List of Maps.
Approach 2:
#Query(
value = "SELECT p.*, c.*, s.*, d.* from patient p, consult c ,script s,dispense d "
+ " where p.patient_id=c.patient_id "
+ " and c.consult_id = d.consult_id "
+ " and c.fk_script_id =s.script_id"
+ " and c.consult_id=?1 ",
nativeQuery = true
)
List<Map<String, Object>> findInvoiceByConsultId(Long consultId);

Jena Location Mapping failed to find configuration

i am working with Jena Text Search using SPARQL. It has succeed in compile time and run time but it doesn't show the desired result which is the result should show the URI and the intended text. It looks like error messages but i get the failed description below:
DEBUG org.apache.jena.util.LocationMapper - Failed to find configuration: file:location-mapping.rdf;file:location-mapping.n3;file:location-mapping.ttl;file:etc/location-mapping.rdf;file:etc/location-mapping.n3;file:etc/location-mapping.ttl
DEBUG org.apache.jena.riot.system.stream.JenaIOEnvironment - Failed to find configuration: location-mapping.ttl;location-mapping.rdf;location-mapping.n3;etc/location-mapping.rdf;etc/location-mapping.n3;etc/location-mapping.ttl
The full codes show below:
public class JenaTextSearch {
static {LogCtl.setLog4j();
BasicConfigurator.configure();}
static Logger log = LoggerFactory.getLogger("JenaTextSearch");
public static void main (String ...argv)
{
Dataset ds = createCode();
//loadData(ds, "data.ttl");
queryData(ds);
}
public static Dataset createCode()
{
//base data
Dataset ds1 = DatasetFactory.create();
Model defaultModel = ModelFactory.createDefaultModel();
defaultModel.read("to_index/data.ttl", "N-TRIPLES");
ds1.setDefaultModel(defaultModel);
//define the index mapping
EntityDefinition entDef = new EntityDefinition ("uri", "text", ResourceFactory.createProperty(App.URI_PREFIX,"content"));
Directory dir = null;
try {
dir = new SimpleFSDirectory(Paths.get("index")); //lucene index directory
}
catch (IOException e) {
e.printStackTrace();
}
//join together into a dataset
Dataset ds = TextDatasetFactory.createLucene(ds1, dir, new TextIndexConfig(entDef));
return ds1;
}
public static void queryData(Dataset dataset)
{
String prefix = "PREFIX email: <" + App.URI_PREFIX+">" +
"PREFIX text: <http://jena.apache.org/text#>";
long startTime = System.nanoTime();
System.out.println("Email's content contains 'good'");
String query = "SELECT * WHERE " +
"{?s text:query (email:content 'good')." +
"?s email:content ?text." +
"}" ;
dataset.begin(ReadWrite.READ);
try {
Query q = QueryFactory.create(prefix+"\n"+query);
QueryExecution qexec = QueryExecutionFactory.create(q, dataset);
QueryExecUtils.executeQuery(q, qexec);
}finally { dataset.end();}
long finishTime = System.nanoTime();
double time = (finishTime-startTime)/1.0e6;
System.out.println ("Query "+String.format("FINISH - %.2fms", time));
startTime = System.nanoTime();
System.out.println("Email's content contains 'bad'");
query = "SELECT * WHERE" +
"{(?s ?score ?lit) text:query (email:content 'bad' \"highlight:s:<em class='hiLite'> | e:</em>\")." +
"?s email:content ?text." +
"}" ;
dataset.begin(ReadWrite.READ);
try {
Query q = QueryFactory.create(prefix+"\n"+query);
QueryExecution qexec = QueryExecutionFactory.create(q, dataset);
QueryExecUtils.executeQuery(q, qexec);
} finally { dataset.end() ; }
finishTime = System.nanoTime();
time = (finishTime-startTime)/1.0e6;
System.out.println("Query "+String.format("FINISH - %.2fms", time));
}}
is that a library problem or something? i use Jena 3.9 and 3.13 because it can completely each other, i think. please devise me. thank you.

Join smail Dataframe with large in spark scala, removing duplicates with feature selection

I have two DataFrame. Large with 19 millions rows and small with 180K rows.
Let's say in large DF I have next cols
+-----------------------------------+------------+--------+
| cuid | Col2 | Col3 |
+-----------------------------------+------------+--------+
| 12654467 | Value 1 | 123 |
| 164687948 | Value 2 | 163 |
| 456132456 | Value 3 | 45 |
+-----------------------------------+------------+--------+
And in small DF next:
+-----------------------------------+
| cuid |
+-----------------------------------+
| 12654467 |
+-----------------------------------+
And output must be
+-----------------------------------+------------+--------+
| cuid | Col2 | Col3 |
+-----------------------------------+------------+--------+
| 12654467 | Value 1 | 123 |
+-----------------------------------+------------+--------+
I've tried next
val joinedDF = smallDF.join(largeDF, Seq("cuid"), "inner")
But in joinedDF I have more, than 180K rows (6 millions). Can anybody know how solve this problem?
UPD - In large and in small DF I have duplicates by cuid, but they have different values in other columns, so I can't grouping by cuid.
So, I have next question - how I can do features selection with other cols and removing duplicates?
This work perfectly for me.
Let's define our input sources:
big.csv
cuid,col2,col3
1,what,bye
2,word,random
3,like,random
4,why,this
5,hello,number
6,bye,train
7,music,word
8,duck,bag
9,car,noise
10,crying,baby
small.csv
cuid
1
4
7
7
The code:
import org.apache.spark.sql.*;
import scala.collection.Seq;
import java.io.Serializable;
public class Foo {
private static final SparkSession spark = new SparkSession
.Builder()
.master("local[*]")
.getOrCreate();
public static void main(String[] args) {
Dataset<BigRow> bigDataset = spark
.read()
.option("header", true)
.csv(".\\resources\\big.csv")
.as(Encoders.bean(BigRow.class));
bigDataset.show();
bigDataset.printSchema();
Dataset<SmallRow> smallDataset = spark
.read()
.option("header", true)
.csv(".\\resources\\small.csv")
.as(Encoders.bean(SmallRow.class));
smallDataset.show();
smallDataset.printSchema();
Dataset<Row> joined = bigDataset
.join(smallDataset, "cuid");
joined.show();
}
private static class SmallRow implements Serializable {
private String cuid;
public SmallRow() {}
public String getCuid() {
return cuid;
}
public void setCuid(String cuid) {
this.cuid = cuid;
}
public SmallRow withCuid(final String cuid) {
this.cuid = cuid;
return this;
}
}
private static class BigRow implements Serializable {
private String cuid;
private String col2;
private String col3;
public BigRow() {}
public String getCuid() {
return cuid;
}
public void setCuid(String cuid) {
this.cuid = cuid;
}
public String getCol2() {
return col2;
}
public void setCol2(String col2) {
this.col2 = col2;
}
public String getCol3() {
return col3;
}
public void setCol3(String col3) {
this.col3 = col3;
}
public BigRow withCuid(final String cuid) {
this.cuid = cuid;
return this;
}
public BigRow withCol2(final String col2) {
this.col2 = col2;
return this;
}
public BigRow withCol3(final String col3) {
this.col3 = col3;
return this;
}
}
}
my output is:
+----+-----+----+
|cuid| col2|col3|
+----+-----+----+
| 1| what| bye|
| 4| why|this|
| 7|music|word|
| 7|music|word|
+----+-----+----+
Consider using distinct to remove duplicates
Dataset<Row> noDuplicates = joined
.dropDuplicates("cuid");
noDuplicates.show();
Hope this help. Thomas.

Dynamic JPQL query qith JOIN

Had to write a jpql query, based on the input need to add and condition and for some input had to need JOIN queries.
#Override
public List<IncidentHdr> fetchIncidents(IncidentHdrDto incidentHdrDto) {
StringBuilder query = new StringBuilder();
query.append(ReposJPQL.GET_INCIDENT_DETAILS);
Map<String, Object> parameters = new HashMap<String, Object>();
List<String> criteria = new ArrayList<String>();
if(incidentHdrDto.getIncidentId() > 0) {
criteria.add("inc.incidentId = :incidentId");
parameters.put("incidentId", incidentHdrDto.getIncidentId());
}
if(incidentHdrDto.getCatCode() > 0) {
criteria.add("inc.catCode = :catCode");
parameters.put("catCode", incidentHdrDto.getCatCode());
}
if(incidentHdrDto.getType != null) {
//here i need to generate a join query
//SELECT * FROM INCIDENT JOIN CATEGORY_MAST ON(INCIDENT.CAT_CODE = CATEGORY_MAST.CAT_CODE) WHERE CATEGORY_MAST.TYPE_CODE = 16
}
Query q = em.createQuery(query.toString());
logger.info("Get Incidents Query : "+query.toString());
for (Entry<String, Object> entry : parameters.entrySet()) {
q.setParameter(entry.getKey(), entry.getValue());
}
List<IncidentHdr> incidentHdrs = q.getResultList();
return incidentHdrs;
}
where as ReposJPQL is the base query which had a where condition.
public interface ReposJPQL {
public String GET_INCIDENT_DETAILS = "SELECT inc FROM IncidentHdr inc WHERE 1 = 1" ;
}

Jersey REST consumer over https

I was using this Jersey annotated Rest consumer POJO without any issue over http, but then we had to start deploying our app over HTTPS.
I am getting a big fat 404, and I concluded, that everything else worked in the code (which is running over MULE beautifully btw) and my POJO simply doesn't consume HTTPS requests.
I suspect that
I am out of luck and Jersey doesn't speak https and I have to redo something here or revert back the part to http
There is a pretty little annotation that i add and voiala! all good.
Obviously, hoping for 2. here.
Here is the code:
package org.acme.api;
import java.net.UnknownHostException;
import java.util.List;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.POST;
import javax.ws.rs.PathParam;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBList;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;
import com.mongodb.DBObject;
import com.mongodb.WriteResult;
import com.mongodb.util.JSON;
import com.mongodb.DB;
/**
REST Web service implementation.
#author menashe#acme.org
*/
#Path("/")
public class Product {
MongoClient client = null;
DB db = null;
DBCollection products = null;
public Product() throws UnknownHostException {
this.client = new MongoClient(new ServerAddress("localhost", 27027));
this.db = this.client.getDB("dailysale");
this.products = this.db.getCollection("products");
}
#GET
#Produces("application/json")
#Path("/product/{productId}")
public String retrieveProduct(#PathParam("productId") Integer productId) {
String product;
try{
DBObject query = new BasicDBObject("productId", String.valueOf(productId));
product = this.products.findOne(query).toString();
} catch(Exception e) {
product = "{ error: 'We were not able to find product with Id: '" + productId + ". " + e.getLocalizedMessage() + " }";
}
return product;
}
#GET
#Produces("application/json")
#Path("/product/grid/{query}")
#HeaderParam("range")
public Response listProducts(#HeaderParam("range") String range, #PathParam("query") String query) {
Integer pageNum = 1;
Integer pageSize = 10;
Integer resultCount = null;
BasicDBList result = new BasicDBList();
Integer firstItem = (pageNum - 1 ) * pageSize;
Long allProductsCount = null;
Integer lastItem = null;
DBObject searchQuery = new BasicDBObject("$regex", query);
try {
DBCursor productListCursor = products.find(searchQuery).skip(firstItem).limit( pageSize );
List<DBObject> productList = productListCursor.toArray();
for(DBObject product : productList) {
result.add(this.itemToGridConverter(product));
}
resultCount = productList.size();
allProductsCount = products.count();
lastItem = firstItem + resultCount - 1;
} catch(Exception e) {
result = new BasicDBList();
result.add(new BasicDBObject("error", "We were not able to retrieve all products with pageSize: " + pageSize + " and pageNumber " + pageNum + ". " + e.getLocalizedMessage() ));
}
return Response.ok(result).header("Content-Range", "items " + firstItem + "-" + lastItem + "/" + allProductsCount).build();
}
#GET
#Produces("application/json")
#Path("/product/grid/")
#HeaderParam("range")
public Response listProducts(#HeaderParam("range") String range) {
Integer pageNum = 1;
Integer pageSize = 10;
Integer resultCount = null;
BasicDBList result = new BasicDBList();
Integer firstItem = (pageNum - 1 ) * pageSize;
Long allProductsCount = null;
Integer lastItem = null;
try {
DBCursor productListCursor = products.find().skip(firstItem).limit( pageSize ).sort( new BasicDBObject( "sku", 1)) ;
List<DBObject> productList = productListCursor.toArray();
for(DBObject product : productList) {
result.add(this.itemToGridConverter(product));
}
resultCount = productList.size();
allProductsCount = products.count();
lastItem = firstItem + resultCount - 1;
} catch(Exception e) {
result = new BasicDBList();
result.add(new BasicDBObject("error", "We were not able to retrieve all products with pageSize: " + pageSize + " and pageNumber " + pageNum + ". " + e.getLocalizedMessage() ));
}
return Response.ok( result ).header("Content-Range", "items " + firstItem + "-" + lastItem + "/" + allProductsCount).build();
}
#GET
#Produces("application/json")
#Path("/product/grid/?{sort}")
#HeaderParam("range")
public Response listProductsWithSort(#HeaderParam("range") String range, #PathParam("sort") String sorting) {
Response response = null;
return response;
}
#PUT
#Produces("application/json")
#Path("/product")
public String createProduct(String productJson) {
DBObject product = null;
String result;
try{
product = (DBObject)JSON.parse(productJson);
WriteResult wResult =this.products.insert(product);
result = wResult.toString();
}
catch(Exception e){
result = "{ error: 'We were not able to insert the product.' " + e.getLocalizedMessage() + " }";
}
return result;
}
#POST
#Produces("application/json")
#Path("/product/{productId}")
public String updateProduct(#PathParam("productId") Integer productId, String productJson) {
DBObject product = null;
DBObject query = new BasicDBObject();
String result = null;
try{
product = (DBObject)JSON.parse(productJson);
query.put("productId", productId.toString());
WriteResult wResult = this.products.update(query, product);
result = wResult.toString();
}
catch(Exception e){
result = "{ error: 'We were not able to update the product.' " + e.getLocalizedMessage() + " }";
}
return result;
}
#DELETE
#Produces("application/json")
#Path("/product/{productId}")
public String deleteProduct(#PathParam("productId") Integer productId) {
return "{ error: 'This function is not implemented [delete].' }";
}
private DBObject itemToGridConverter(DBObject product) {
DBObject item = new BasicDBObject();
BasicDBList images = (BasicDBList)product.get("images");
BasicDBObject firstImage = (BasicDBObject)images.get(0);
item.put("productId", product.get("productId"));
item.put("sku", product.get("sku"));
item.put("image", firstImage.get("imageurl"));
BasicDBList spec = (BasicDBList)product.get("productSpecifics");
BasicDBObject firstSpec = (BasicDBObject)spec.get(0);
BasicDBObject attributes = (BasicDBObject)product.get("productAttributes");
item.put("name", firstSpec.get("title"));
item.put("cost", "no source");
item.put("list_price", attributes.get("defaultsalePrice"));
item.put("qty_available", product.get("qtyonHand"));
item.put("condition", "no source");
item.put("active", "true".equals(product.get("active")) ? "Yes" : "No");
item.put("manufacturer", attributes.get("manufacturer"));
item.put("part_number", attributes.get("manufacturerPartNumber"));
item.put("date_created", product.get("_id"));
return item;
}
}
Thanks much.
UPDATE:
I fixed the issue by fixing the path. The issue was how MULE resolves scope boundaries and here the original #Path / was actually in the previous scope. Now that we changed the flow the #Path became /controllers/.
Uyodiin Mevin.