"Call require API level..." from Google App Engine - google-app-engine

I am trying to use ThreadLocalRandom.current() in my GAE endpoint via Android Studio, but getting this error:
Call requires API level 21 (current min is 1)
ThreadLocalRandom is not even an Android API library!
Does anyone have any idea? Thanks!

Try adding the following annotation on top of whatever method your ThreadLocalRandom.current() line is contained in:
#RequiresApi(api = Build.VERSION_CODES.L)
For example:
#RequiresApi(api = Build.VERSION_CODES.L)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
}

Related

nancy selfhost, with dryioc and bootstrapper -> Method not found exception

At work we require a small application, and decided to test some things we are not really familiar with for this project as well.
I started with a console app, using topshelf to host nancy via the nancy selfhosting package.
All of this works.
Now I wanted to wire in the DryIoc container into the nancy bootstrapper and got the following error:
System.MissingMethodException
HResult=0x80131513
Message=Method not found: 'DryIoc.Rules DryIoc.Rules.With(DryIoc.FactoryMethodSelector, DryIoc.ParameterSelector, DryIoc.PropertiesAndFieldsSelector, Boolean)'.
Source=Nancy.Bootstrappers.DryIoc
StackTrace:
at Nancy.Bootstrappers.DryIoc.DryIocNancyBootstrapper.<GetApplicationContainer>b__0(Rules rules)
at DryIoc.Container..ctor(Func`2 configure, IScopeContext scopeContext)
at Nancy.Bootstrappers.DryIoc.DryIocNancyBootstrapper.GetApplicationContainer()
at Nancy.Bootstrapper.NancyBootstrapperBase`1.Initialise()
at Nancy.Hosting.Self.NancyHost..ctor(INancyBootstrapper bootstrapper, HostConfiguration configuration, Uri[] baseUris)
at Nancy.Hosting.Self.NancyHost..ctor(Uri baseUri, INancyBootstrapper bootstrapper, HostConfiguration configuration)
at Segrey.Licensing.Web.WebService.Start() in I:\git projects\Segrey.Licensing\Segrey.Licensing.Web\WebService.cs:line 21
at Segrey.Licensing.Service.Program.<>c.<CreateHost>b__1_2(WebService ls) in I:\git projects\Segrey.Licensing\Segrey.Licensing.Service\Program.cs:line 26
at Topshelf.ServiceConfiguratorExtensions.<>c__DisplayClass2_0`1.<WhenStarted>b__0(T service, HostControl control)
at Topshelf.Builders.DelegateServiceBuilder`1.DelegateServiceHandle.Start(HostControl hostControl)
at Topshelf.Hosts.ConsoleRunHost.Run()
My bootstrapper: empty, no registrations yet as I first wanted to test this out
before making it more complex
public class Bootstrapper : DryIocNancyBootstrapper
{
protected override void ApplicationStartup(IContainer container, IPipelines pipelines)
{
//No registrations should be performed in here, however you may
//resolve things that are needed during application startup.
base.ApplicationStartup(container, pipelines);
}
protected override void ConfigureApplicationContainer(IContainer container)
{
//Perform registation that should have an application lifetime
base.ConfigureApplicationContainer(container);
}
protected override void ConfigureRequestContainer(IContainer container, NancyContext context)
{
//Perform registrations that should have a request lifetime
base.ConfigureRequestContainer(container, context);
}
protected override void RequestStartup(IContainer container, IPipelines pipelines, NancyContext context)
{
// No registrations should be performed in here, however you may
// resolve things that are needed during request startup.
base.RequestStartup(container, pipelines, context);
}
}
And in my .Start method for the service via topshelf where the bootstrapper gets assigned
public void Start()
{
var hostConfig = new HostConfiguration() { UrlReservations = new
UrlReservations { CreateAutomatically = true } };
var uri = new Uri(_hostUrl);
_nancyHost = new NancyHost(uri, new Bootstrapper(), hostConfig);
_nancyHost.Start();
}
Error occurs on new NancyHost(uri, new Bootstrapper(), hostConfig); as soon as I add new Bootstrapper() into the arguments
Sounds like a versioning issue. Check your .config file for binding redirects for dryioc.
It appears DryIocNancyBootstrapper thinks it's using version X of DryIOC, but instead it's using version Y (due to a binding redirect), which doesn't have that method (either it was removed or it's an older version that doesn't yet have it).
Figure out what version DryIocNancyBootstrapper wants (i.e., version X in the example above) and reference that version.

(Android Studio) Connecting an app to Google Endpoints Module

I'm having trouble following the second step here.
I really don't understand how this sample does anything other than return a simple toast message. How does it utilize the API to display that message?
class EndpointsAsyncTask extends AsyncTask<Pair<Context, String>, Void, String> {
private static MyApi myApiService = null;
private Context context;
#Override
protected String doInBackground(Pair<Context, String>... params) {
if(myApiService == null) { // Only do this once
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
#Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
// end options for devappserver
myApiService = builder.build();
}
context = params[0].first;
String name = params[0].second;
try {
return myApiService.sayHi(name).execute().getData();
} catch (IOException e) {
return e.getMessage();
}
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}
I'm afraid my this sample is too complex for my limited knowledge. How exactly do I "talk" to the Google Endpoints Module when running an app? Specifically, What is EndpointsAsyncTask();?
Are there any resources listing all the methods available to me? Is there a simpler example of an app communicating with a Google Cloud Endpoint?
The service methods available to you are defined by the backend source in section 1.
In the example you posted, this line: myApiService.sayHi(name).execute()
is an actual invocation call to the backend that you defined by annotating #ApiMethod("sayHi") on the method in the MyEndpoint.java class of your backend module.
The reason your Android app defines an EndpointsAsyncTask is because slow operations such as calls that hit the network need to happen off of the UI thread to avoid locking the UI. The demo simply puts the returned value into a Toast but you could modify onPostExecute() to do whatever you'd like with the result.
For more info on Google Endpoints check out:
https://cloud.google.com/appengine/docs/java/endpoints/
And for info about using an Android AsyncTask look here:
http://developer.android.com/reference/android/os/AsyncTask.html

Can I know which endpoint is finally targeted when using load balancer?

I have a route using a customized load balancer as,
from("timer://myTimer?period=2000")
.loadBalance(new MyCustomLoadBalancer())
.to("mock:em1").to("mock:em2").to("mock:em3")
.end();
In the customized balancer class, it seems only processors can be gotten.
public class MyCustomLoadBalancer extends SimpleLoadBalancerSupport {
public void process(Exchange exchange) throws Exception {
List<Processor> pList = getProcessors();
.......
//It is wanted to log which endpoint is finally targeted.
foo.process(exchange);
}
}
But here, I want to log actually which endpoint is targeted when using this load balancer.
In product environment, Jetty or HTTP endpoints will be used instead of these mock endpoints.
Is there a way to realized this?
===================================================================
Based on the suggestion from Ibsen, I used the Jetty endpoint to do test.
from("jetty:http://0.0.0.0:8043?matchOnUriPrefix=true")
.loadBalance(new MyCustomLoadBalancer())
.to("jetty:http://localhost:80?bridgeEndpoint=true&throwExceptionOnFailure=false")
.to("jetty:http://www.google.com?bridgeEndpoint=true&throwExceptionOnFailure=false")
.end();
But the Processors are not class of SendProcessor("foo instanceof SendProcessor" returns false), so I can't get the endpoint by getDestination.
I believe there should be some relationship between the endpoint and processor.
Could you give me more help?
Thanks.
The Processor is a SendProcessor where you can get the endpoint it will send the exchange to.
if (foo instanceof SendProcessor) {
SendProcessor send = (SendProcessor) foo;
Endpoint dest = send.getDestination();
...
}

NoClassDefFoundError: javax.naming.directory.InitialDirContext is a restricted class. Using CCS (GCM) in Google App Engine

Im trying to implement google's Cloud Connection Server with Google App Engine following this tutorial -
Implementing an XMPP-based App Server. I copied latest smack jars from http://www.igniterealtime.org/projects/smack/ (smack.jar and smackx.jar), put them in WEB-INF/lib and added them to the classpath (im using eclipse).
In the code sample in the first link i posted, the XMPPConnection is initiated in a 'main' method. Since this is not really suitable to GAE i created a ServletContextListener and added it to web.xml.
public class GCMContextListener implements ServletContextListener {
private static final String GCM_SENDER_ID = "*GCM_SENDER_ID*";
private static final String API_KEY = "*API_KEY*";
private SmackCcsClient ccsClient;
public GCMContextListener() {
}
#Override
public void contextInitialized(ServletContextEvent arg0) {
final String userName = GCM_SENDER_ID + "#gcm.googleapis.com";
final String password = API_KEY;
ccsClient = new SmackCcsClient();
try {
ccsClient.connect(userName, password);
} catch (XMPPException e) {
e.printStackTrace();
}
}
#Override
public void contextDestroyed(ServletContextEvent arg0) {
try {
ccsClient.disconnect();
} catch (XMPPException e) {
e.printStackTrace();
}
}
}
web.xml
<web-app>
<listener>
<listener-class>com.myserver.bootstrap.GCMContextListener</listener-class>
</listener>
</web-app>
Now, when i start the GAE server i get the following exception :
java.lang.NoClassDefFoundError: javax.naming.directory.InitialDirContext is a restricted class. Please see the Google App Engine developer's guide for more details.
i searched the "Google App Engine developer's guide for more details" but couldnt find anything about this. can you please help me ?
Google App Engine restricts access to certain JRE classes. In fact they published a whitelist that shows you which classes are useable. It seems to me that the Smack library might require some reference to a directory context (maybe to create the XMPP messages?) and that is why your servlet causes this exception. The javax.naming.directory is not in the whitelist.
I'm currently working on setting up a GCM Server as well. It seems to me that you need to read through the example and see what that main method is doing. What I see is a connection to the GCM server:
try {
ccsClient.connect(userName, password);
} catch (XMPPException e) {
e.printStackTrace();
}
Then a downstream message being sent to a device:
// Send a sample hello downstream message to a device.
String toRegId = "RegistrationIdOfTheTargetDevice";
String messageId = ccsClient.getRandomMessageId();
Map<String, String> payload = new HashMap<String, String>();
payload.put("Hello", "World");
payload.put("CCS", "Dummy Message");
payload.put("EmbeddedMessageId", messageId);
String collapseKey = "sample";
Long timeToLive = 10000L;
Boolean delayWhileIdle = true;
ccsClient.send(createJsonMessage(toRegId, messageId, payload, collapseKey,
timeToLive, delayWhileIdle));
}
These operations would be completed at some point during your application's lifecycle, so your servlet should support them by providing the methods the example is implementing, such as the connect method that appears in the first piece of code that I pasted here. It's implementation is in the example at line 235 if I'm not mistaken.
As the documentation says, the 3rd party application server, which is what you're trying to implement using GAE, should be:
Able to communicate with your client.
Able to fire off properly formatted requests to the GCM server.
Able to handle requests and resend them as needed, using exponential back-off.
Able to store the API key and client registration IDs. The API key is included in the header of POST requests that send messages.
Able to store the API key and client registration IDs.
Able to generate message IDs to uniquely identify each message it sends.

GWT RPC method name at App Engine server log

our project runs on GWT and Java App Engine and we use the standard GWT RPC mechanism.
App engine adds log trace for each RPC call, but it just logs the servlet URL and not the called method.
We would like to add the method name to the log URL.
We have tried extending RpcRequestBuilder class, overriding doCreate and adding the method name to the URL, but the problem is that at this point the method name is unknown - it's known later at doSetRequestData (as part of the data string).
Thanks
Itzik
In each rpc implementation you can override one of readContent and processCall and add logging.
#Override
public String processCall(String payload) throws SerializationException {
// TODO Auto-generated method stub
String processCall = super.processCall(payload);
Logger.getLogger("").info(processCall);
return processCall;
}
#Override
protected String readContent(HttpServletRequest request)
throws ServletException, IOException {
// TODO Auto-generated method stub
String readContent = super.readContent(request);
Logger.getLogger("").info(readContent);
return readContent;
}
Log Line
6|0|4|http://127.0.0.1:8888/_4021625/|35C4974968FC8F8A9A7EA4881FD49F57|com.bitdual.client.LogMeService|logmemethod|1|2|3|4|0|

Resources