I have this simple ednpoint method:
#ApiMethod(name = "createCategory")
public RCategory createCategory(#Named("userHash")String userHash, #Nullable #Named("synchronously")Boolean synchronously, Category category) throws AccessForbiddenException, DuplicateEntityNameException, SubscriptionRequiredException {
User user = OwlEndpoint.getUser(userHash);
if (!user.hasSubscriptionActive()) throw new SubscriptionRequiredException();
//Sprawdzam czy w profilu uzytkownika jest wiecej niz on sam (o ile w ogole ma profil)
List<Long> usersInProfileIds = getUsersInProfilesIds(user);
if (ofy().load().type(Category.class).filter("creatorId in", usersInProfileIds).filter("name", category.getName()).count() > 0) throw new DuplicateEntityNameException();
category.setCreatorId(user.getId());
if (synchronously != null && synchronously) ofy().save().entity(category).now();
else ofy().save().entity(category);
return new RCategory(category, user.getId());
}
It works just fine on the DEV server, but after uploading to GAE it started to fail. I found this in the logs, but that doesn't make sense to me:
Request URL: https://myapp.appspot.com/_ah/api/owlendpoint/v1/createCategory/0A71A4A761C2B0C49BE3CE4ED19E78E93911DAE1E53732BE5635B29F923DBBFD5C54DEBE7F80831364D8255861D46878ADB657D0DDA95EEAF19956A6C5967CADF903543D1DA577677FEAEC70F0019B055C4CBA168A4A188D41393A9BF08834A92F8BB13D5E03F7F901C1281878BE8B79
Method: myappendpoint.createCategory
Error Code: 400
Reason: badRequest
Message: java.lang.IllegalArgumentException: offset may not be above 1000
I made this method:
#SuppressWarnings("rawtypes")
public static boolean hasItems(Query query) {
Iterator it = query.iterator();
return it.hasNext();
}
I'm using it to define, if there is at least one element on the query without using count(). Still would like to know how can I use count() and how can not...
Related
I fail to reload my resource bundle class to reflect the changed translations (made my end-user) on page. Although getContent method executes and all translations as key/value fetched from database and object[][] returned from getContent method successfully. this happens after each time I clear the cache and refresh the jsf page through actionListener.
ResourceBundle.clearCache();
Also I tried to use the below and got the same result.
ResourceBundle.clearCache(Thread.currentThread().GetContextClassLoader());
Why WLS always see the old one? Am I miss something?
versions: 12.2.1.1.0 and 12.2.1.3.0
The end user - after making the translations and contributing to the internationalization of the project, the translations are saved to the database,
The process to inforce these operations are done through the following steps:
Create a HashMap and load all the resource key/vale pairs in the map
from the database:
while (rs.next()) {
bundle.put(rs.getString(1), rs.getString(2));
}
Refresh the Bundle of your application
SoftCache cache =
(SoftCache)getFieldFromClass(ResourceBundle.class,
"cacheList");
synchronized (cache) {
ArrayList myBundles = new ArrayList();
Iterator keyIter = cache.keySet().iterator();
while (keyIter.hasNext()) {
Object key = keyIter.next();
String name =
(String)getFieldFromObject(key, "searchName");
if (name.startsWith(bundleName)) {
myBundles.add(key);
sLog.info("Resourcebundle " + name +
" will be refreshed.");
}
}
cache.keySet().removeAll(myBundles);
Getthe a String from ResourceBoundle of your application:
for (String resourcebundle : bundleNames) {
String bundleName =
resourcebundle + (bundlePostfix == null ? "" : bundlePostfix);
try {
bundle = ResourceBundle.getBundle(bundleName, locale, getCurrentLoader(bundleName));
} catch (MissingResourceException e) {
// bundle with this name not found;
}
if (bundle == null)
continue;
try {
message = bundle.getString(key);
if (message != null)
break;
} catch (Exception e) {
}
}
I have following processor, when I run it from my route I get the following error. I know exchange body is not null and you can see it in logs below. What is wrong with my usage of SimpleBuilder here ?
public class UpdateCustomerProcessor implements Processor {
public static final Logger log = LoggerFactory.getLogger(UpdateCustomerProcessor.class);
public void process(Exchange exchng) throws Exception {
Customer c = (Customer) exchng.getIn().getBody(Object[].class)[0];
System.out.println("Updating customer " + c.getFirstName() + " " + c.getLastName());
System.out.println(SimpleBuilder.simple("Hello ${body.getFirstName()}").evaluate(exchng, String.class));
exchng.getOut().setBody(new Object[] {});
}
}
log->Updating customer aaa bbb
error-> org.apache.cxf.interceptor.Fault: Failed to invoke method: .getFirstName() on null due to: org.apache.camel.language.bean.RuntimeBeanExpressionException: Failed to invoke method: getFirstName() on null
I can't make sense of the "null"-exception, since exchange in appears to be filled. Nevertheless, your expression looks incorrect - since your exchange.in seems to hold an array, it should be:
SimpleBuilder.simple("Hello ${body[0].firstname}").evaluate(exchng, String.class))
I wonder if my case is consistency issue...
I have an entity class Player, which has a field lastAttackDate. I set lastAttackDate = sysdate in a transaction, then I commit that transaction, and then I query for players with lastAttackDate < sysdate - 10min (please see the simplified code).
private static final Logger log = Logger.getLogger(MyEndpoint.class.getName());
#ApiMethod(name = "attack")
public MyResult attack(#Named("id") Long id, User user) throws Exception, OAuthRequestException, IOException {
PersistenceManager mgr = null;
Player defender = null;
Transaction tx = null;
try {
mgr = getPersistenceManager();
tx = mgr.currentTransaction();
tx.begin();
long now = new Date().getTime();
defender = getPlayer(mgr, id);//I get player by param ID
defender.setLastAttackDate(now);
tx.commit(); //mgr.close(); mgr = getPersistenceManager();--> I tried that, it did not help
long param = now - 10*60*1000;//sysdate - 10 minutes
Query q = pm.newQuery("select from " + Player.class.getName() +" where lastAttackDate < lastAttackDateParam parameters long lastAttackDateParam");
Set<Player> result = new HashSet<Player>();
result.addAll((List<Player>) q.execute(param));
Iterator<Player> it = results.iterator();
while(it.hasNext())
{
Player p = it.next();
if (p.getLastAttackDate() >= param)
{
log.log(Level.SEVERE, "It really just gave me a result that doesn't meet the criteria");//defender (the recently updated player) falls in this category
it.remove();
}
}
}
finally {
if (tx != null && tx.isActive())
tx.rollback();
if (mgr != null)
mgr.close();
return null;
}
}
What bothers me is that this query still gives me defender as a result. What bothers me even more, is that if I iterate through result and I check if it meets the criteria, I can see that it does not. If it was consistency issue, I'd suspect that getLastAttackDate() should return old, not updated value, but it gives the right one, the most recent one. What do I do wrong? What can I do to make it work?
At the moment, I iterate through the result set and remove the entries that do not meet my search criteria, but it is expensive (reads, cpu time, possibly additional query to try again).
I am confused to using auto-generated endpoint class. I want to use generated endpoint to insert new object into datastore. But, an exception is throwing.
fooEndpoint.insertFoo(foo); // throws null pointer exception
My entity class is similar with the given example at this source: https://developers.google.com/appengine/docs/java/datastore/jpa/overview.
Here is my entity:
#Entity
public class Foo {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Key ID;
Here is the stack trace:
java.lang.NullPointerException
at org.datanucleus.api.jpa.JPAEntityManager.find(JPAEntityManager.java:318)
at org.datanucleus.api.jpa.JPAEntityManager.find(JPAEntityManager.java:256)
at com.FooEndpoint.containsFoo(FooEndpoint.java:150)
at com.FooEndpoint.insertFoo(FooEndpoint.java:96)
On the other side, I can insert new object when I use the EntityManager persist method. Because, this does not check exist or not on the datastore.
I expect that, classEndpoint insert method should save the object and assing auto key to ID field.
Or I need to initialize the ID field.
Here is auto-generated endpoint class insertFoo method.
/**
* This inserts a new entity into App Engine datastore. If the entity already
* exists in the datastore, an exception is thrown.
* It uses HTTP POST method.
*
* #param foo the entity to be inserted.
* #return The inserted entity.
*/
public Foo insertFoo(Foo foo) {
EntityManager mgr = getEntityManager();
try {
if (containsFoo(foo)) {
throw new EntityExistsException("Object already exists");
}
mgr.persist(foo);
} finally {
mgr.close();
}
return foo;
}
Here is the containsFoo method
private boolean containsFoo(Foo foo) {
EntityManager mgr = getEntityManager();
boolean contains = true;
try {
Foo item = mgr.find(Foo.class, foo.getID()); // exception occurs here
if (item == null) {
contains = false;
}
} finally {
mgr.close();
}
return contains;
}
foo.getID() is null. Because, it is new object. I am expecting that, app engine creates a key for it. Or I need to explicitly create a key for it?
Other fields in Foo class are simple types such as String and booleans.
Thanks for your time.
I had exactly the same problem.
I will present the way I worked around it.
Original auto-generated Endpoints class relevant code:
private boolean containsFoo(Foo foo) {
EntityManager mgr = getEntityManager();
boolean contains = true;
try {
Foo item = mgr.find(Foo.class, foo.getID());
if (item == null) {
contains = false;
}
} finally {
mgr.close();
}
return contains;
}
Changed relevant code to include a null check for the entity object that is passed as an argument.
private boolean containsFoo(Foo foo) {
EntityManager mgr = getEntityManager();
boolean contains = true;
try {
// If no ID was set, the entity doesn't exist yet.
if(foo.getID() == null)
return false;
Foo item = mgr.find(Foo.class, foo.getID());
if (item == null) {
contains = false;
}
} finally {
mgr.close();
}
return contains;
}
This way it will work as supposed, although I'm confident that more experienced answers and explanations will appear.
I was having the same exact problem after using the Eclipse Plugin to autogenerate the cloud endpoints (by selecting "Google > Generate Cloud Endpoint Class").
Following your advice, I added:
if(foo.getID() == null) // replace foo with the name of your own object
return false;
The problem was solved.
How is that Google hasn't updated the autogenerated code yet as this must be a highly recurring issue?
Thanks for the solution.
Having performed a pg_dump of an existing posgresql schema, I have an sql file containing a number of table population statements using the copy.
COPY test_table (id, itm, factor, created_timestamp, updated_timestamp, updated_by_user, version) FROM stdin;
1 600 0.000 2012-07-17 18:12:42.360828 2012-07-17 18:12:42.360828 system 0
2 700 0.000 2012-07-17 18:12:42.360828 2012-07-17 18:12:42.360828 system 0
\.
Though not standard this is part of PostgreSQL's PLSQL implementation.
Performing a flyway migration (via the maven plugin) I get:
[ERROR] Caused by org.postgresql.util.PSQLException: ERROR: unexpected message type 0x50 during COPY from stein
Am I doing something wrong, or is this just not supported?
Thanks.
The short answer is no.
The one definite problem is that the parser is currently not able to deal with this special construct.
The other question is jdbc driver support. Could you try and see if this syntax generally supported by the jdbc driver with a single createStatement call?
If it is, please file an issue in the issue tracker and I'll extend the parser.
Update: This is now supported
I have accomplished this for Postgres using
public abstract class SeedData implements JdbcMigration {
protected static final String CSV_COPY_STRING = "COPY %s(%s) FROM STDIN HEADER DELIMITER ',' CSV ENCODING 'UTF-8'";
protected CopyManager copyManager;
#Override
public void migrate(Connection connection) throws Exception {
log.info(String.format("[%s] Populating database with seed data", getClass().getName()));
copyManager = new CopyManager((BaseConnection) connection);
Resource[] resources = scanForResources();
List<Resource> res = Arrays.asList(resources);
for (Resource resource : res) {
load(resource);
}
}
private void load(Resource resource) throws SQLException, IOException {
String location = resource.getLocation();
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(location);
if (inputStream == null) {
throw new FlywayException("Failure to load seed data. Unable to load from location: " + location);
}
if (!inputStream.markSupported()) {
// Sanity check. We have to be able to mark the stream.
throw new FlywayException(
"Failure to load seed data as mark is not supported. Unable to load from location: " + location);
}
// set our mark to something big
inputStream.mark(1 << 32);
String filename = resource.getFilename();
// Strip the prefix (e.g. 01_) and the file extension (e.g. .csv)
String table = filename.substring(3, filename.length() - 4);
String columns = loadCsvHeader(location, inputStream);
// reset to the mark
inputStream.reset();
// Use Postgres COPY command to bring it in
long result = copyManager.copyIn(String.format(CSV_COPY_STRING, table, columns), inputStream);
log.info(format(" %s - Inserted %d rows", location, result));
}
private String loadCsvHeader(String location, InputStream inputStream) {
try {
return new BufferedReader(new InputStreamReader(inputStream)).readLine();
} catch (IOException e) {
throw new FlywayException("Failure to load seed data. Unable to load from location: " + location, e);
}
}
private Resource[] scanForResources() throws IOException {
return new ClassPathScanner(getClass().getClassLoader()).scanForResources(getSeedDataLocation(), "", ".csv");
}
protected String getSeedDataLocation() {
return getClass().getPackage().getName().replace('.', '/');
}
}
To use implement the class with the appropriate classpath
package db.devSeedData.dev;
public class v0_90__seed extends db.devSeedData.v0_90__seed {
}
All that is needed then is to have CSV files in your classpath under db/devSeedData that follow the format 01_tablename.csv. Columns are extracted from the header line of the CSV.