问题
I am trying to run a very simple hello world application on Google Cloud with objectify but get an exception when trying to access the datastore for saving an entity.
I am using the latest Google Cloud Tools (1.6.1) for eclipse (Oxygen 4.7.3a) and Java 8. Following the official Google quick star guide I was able to create a standard java project and run the hello word sample app on my local server from eclipse. Since the plugin let you add Objectify libraries to the project I decided to give it a try. Here is the code that I wrote to define an Entity and try to save it to the datastore.
//HelloAppEngine.java
package app;
import java.io.IOException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.googlecode.objectify.ObjectifyService;
import static com.googlecode.objectify.ObjectifyService.ofy;
@WebServlet(
name = "HelloAppEngine",
urlPatterns = {"/hello"}
)
public class HelloAppEngine extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
Car porsche = new Car("2FAST", 4);
ofy().save().entity(porsche).now(); // async without the now()
assert porsche.id != null; // id was autogenerated
Car fetched2 = ofy().load().type(Car.class).id(porsche.id).now();
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
response.getWriter().print("Hello App Engine!\r\n");
response.getWriter().print(porsche.id);
}
public void init() {
ObjectifyService.init();
ObjectifyService.register(Car.class);
}
}
//Car.java
package app;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Index;
@Entity
public class Car {
@Id Long id;
@Index String license;
int color;
Car(String lic, int c) {
license = lic;
color = c;
}
}
When running the project as App Engine standard on localhost I got the following exception:
java.lang.IllegalArgumentException: projectId must match the following pattern: ([a-z\d\-]{1,100}~)?([a-z\d][a-z\d\-\.]{0,99}:)?([a-z\d][a-z\d\-]{0,99})
at com.google.common.base.Preconditions.checkArgument(Preconditions.java:122)
at com.google.cloud.datastore.Validator.validateDatabase(Validator.java:42)
at com.google.cloud.datastore.BaseKey$Builder.<init>(BaseKey.java:58)
at com.google.cloud.datastore.KeyFactory.<init>(KeyFactory.java:35)
at com.google.cloud.datastore.DatastoreHelper.newKeyFactory(DatastoreHelper.java:58)
at com.google.cloud.datastore.DatastoreImpl.newKeyFactory(DatastoreImpl.java:466)
at com.googlecode.objectify.impl.Keys.createRawIncomplete(Keys.java:179)
at com.googlecode.objectify.impl.KeyMetadata.getIncompleteKey(KeyMetadata.java:184)
at com.googlecode.objectify.impl.KeyMetadata.setKey(KeyMetadata.java:153)
at com.googlecode.objectify.impl.KeyPopulator.save(KeyPopulator.java:29)
at com.googlecode.objectify.impl.translate.ClassPopulator.save(ClassPopulator.java:156)
at com.googlecode.objectify.impl.translate.ClassTranslator.saveSafe(ClassTranslator.java:131)
at com.googlecode.objectify.impl.translate.NullSafeTranslator.save(NullSafeTranslator.java:31)
at com.googlecode.objectify.impl.EntityMetadata.save(EntityMetadata.java:113)
at com.googlecode.objectify.impl.WriteEngine.save(WriteEngine.java:69)
at com.googlecode.objectify.impl.SaverImpl.entities(SaverImpl.java:60)
at com.googlecode.objectify.impl.SaverImpl.entity(SaverImpl.java:35)
at app.HelloAppEngine.doGet(HelloAppEngine.java:26)
Any idea what am I missing here? AFAIK as long as I run on the local dev server I don't need a project id.
回答1:
First, you do need to provide a project ID when working with the local emulator, as you discovered. You can't simply omit it. In Eclipse go to Run > Run Configurations > App Engine > App Engine Local Server and select the Cloud Platform tab of your run configuration. In that tab, select a project. This will assign a project ID to be used in the local run. It doesn't matter which project you select. You won't actually connect to it.
As an alternative if you aren't logged in or don't have a Cloud Project, you can instead set the GOOGLE_CLOUD_PROJECT environment variable to a legal string such as MyProjectId in the environment tab of the run configuration.
Beyond that, Objectify 6.0 seems to have an issue working with the bundled datastore emulator in the dev_appserver. It does work with the beta gcloud based datastore emulator. To use that instead, launch a terminal and run
$ gcloud beta emulators datastore start
As the emulator starts up, you will see a message like this one:
[datastore] API endpoint: http://localhost:8081
[datastore] If you are using a library that supports the DATASTORE_EMULATOR_HOST environment variable, run:
[datastore]
[datastore] export DATASTORE_EMULATOR_HOST=localhost:8081
[datastore]
[datastore] Dev App Server is now running.
You need to add the DATASTORE_EMULATOR_HOST environment variable to your Eclipse run configuration in the Environment tab. In this example, you'd set name to DATASTORE_EMULATOR_HOST and value to localhost:8081.
来源:https://stackoverflow.com/questions/50456158/projectid-must-match-the-following-pattern-exception-when-running-objectify-on