NoClassDefFoundError: com/google/appengine/api/search/IndexSpec - google-app-engine

I am using Google App Engine along with Google Datastore and Google Search Api as the backend solution for my App.
Everything has been working fine until 3 days ago when I made a small modification and deployed my code. Then I encountered issues as java.lang.NoClassDefFoundError: com/google/appengine/api/datastore/DatastoreService. I am pretty sure the change I made has nothing to do with this, so I read google document (https://cloud.google.com/appengine/docs/standard/java/datastore/) and find that I need to use Google Cloud Client Library instead of app engine apis. so I added following code in my gradle and started using Client Library for datastore.
implementation 'com.google.cloud:google-cloud-datastore:1.98.0'
But this only fix issue for datastore, the issue for search api still exist. For search, I followed document at https://cloud.google.com/appengine/docs/standard/java/search/ , and I cannot find the replacement solution for it with Google Cloud Client Library (as listed: https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients).
I also read the document for Google Api Client Library (https://developers.google.com/api-client-library/java/apis), also cannot find the solution.
my gradle file:
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'com.google.cloud.tools.appengine'
apply plugin: 'kotlin'
apply plugin: 'kotlin-kapt'
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.google.cloud.tools:appengine-gradle-plugin:1.3.5'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.11"
}
}
version '1.0'
sourceCompatibility = 1.8
repositories {
maven {
url 'https://oss.sonatype.org/content/repositories/snapshots'
}
mavenCentral()
jcenter()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
compile 'com.google.appengine:appengine-api-1.0-sdk:+'
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
compile "org.jetbrains.kotlin:kotlin-stdlib:1.3.11"
compile 'com.google.code.gson:gson:2.8.2'
implementation 'com.google.cloud:google-cloud-datastore:1.98.0'
compile 'jstl:jstl:1.2'
}
appengine {
deploy { // deploy configuration
}
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}

Related

Deploy ASP.NET core 7 Web API with React front end

I wrote an ASP.NET Core 7 web API backend and standalone Javascript React front end. I can deploy the backend to IIS successfully and it works fine through postman. However when I try to deploy the react front end using the method described in this tutorial https://learn.microsoft.com/en-us/visualstudio/javascript/tutorial-asp-net-core-with-react?view=vs-2022
my visual studio just freaks out and crashes. I am trying to figure out how to deploy the front end manually without using the visual studio publish feature.
This is my project setup:
[1]: https://i.stack.imgur.com/cApdk.png
And this is the IIS side where the WEB API backend is currently published:
[2]: https://i.stack.imgur.com/GtJ9O.png
Do I need to create a separate site for the frontend or can I deploy it to the same site as the backend? How can I build the frontend and manually deploy to the IIS?
For the site to work properly, you should build the frontend part in production mode, i.e. use the command npm run build instead of npm run start.
And then move the resulting files to the wwwroot folder inside your NET7 project.
Additionally, you should add static files using the AddStaticFiles method.
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-7.0
Also remember to set the ports correctly, because you can have different ones in the development and production environment, you will do it in launchsetting.json
You just need to change your Program.cs file like below, the you could publish webapi project directly. Every step mentioned in the official document must be completed, and finally add the following code.
namespace WebApplication1
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
else
{
app.UseDefaultFiles();
//app.UseStaticFiles();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
//app.MapControllers();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
// Add this line
endpoints.MapFallbackToFile("/index.html");
});
app.Run();
}
}
}
Test Result

NextJs: The Serverless Function exceeds the maximum size limit of 50mb

I'm new working with NextJs and when trying to deploy my project to Vercel I'm getting the following error:
Error! The Serverless Function "api/auth" is 50.55mb which exceeds the maximum size limit of 50mb.
I have spent a lot of my time trying to find a proper answer but I didn't find any. Here is the code of the api request I'm making:
const { auth: adminAuth } = require("firebase/admin");
export default async function auth(req, res) {
const tokenId = req.query.token;
return new Promise((resolve) => {
adminAuth
.verifyIdToken(tokenId)
.then((user) => {
res.json(user);
resolve();
})
.catch(() => {
res.status(302).send("Invalid authentication");
resolve();
});
});
}
I'll be really grateful if anybody can help me, thanks y'all!
I've been dealing with the same issue. It appears that when bundling the serverless function vercel is pulling in ALL assets within your project. So 50.55MB is likely the size of your current entire build. I'm researching how to only include certain files within the vercel.json but have so far not figured exactly how to do that. For now you could probably just remove a few files from your public assets to get under the limit.
This is likely caused by firebase/admin including everything in the firebase package, not just the "admin" parts.
You can verify this by creating a file with only the import and running #vercel/nft to trace the files.
npm init -y
npm add firebase
echo "const { auth: adminAuth } = require('firebase/admin')" > index.js
npm i -g #vercel/nft
nft print index.js
The entire firebase package is quite large, so its best to follow the recommendation from the firebase team and use the firebase-admin package inside Serverless Functions.
This SDK (firebase) is intended for end-user client access from environments such as the Web, mobile Web (e.g. React Native, Ionic), Node.js desktop (e.g. Electron), or IoT devices running Node.js. If you are instead interested in using a Node.js SDK which grants you admin access from a privileged environment (like a server), you should use the Firebase Admin Node.js SDK (firebase-admin).
source: firebase NPM
You could add .vercelignore file to avoid this
Ref: https://vercel.com/guides/prevent-uploading-sourcepaths-with-vercelignore
# Ignore everything (folders and files) on root only
/*
!api
!vercel.json
!*.html
!*.css

How to add react.js to spring mvc application

I have a Spring MVC application (jsp as a views) and i want to add react.js as a frontend. I have a couple of questions:
1. Where i should place my create-react-app folder or it doesn't matter.
2. Is there a way to run the application from maven (war) only. I mean that i know only one way to run application it is start backend from maven and start react.js from npm start. But this approach requires to use proxy or cors (or i'm wrong). I am using IntellijI IDEA and WebStorm.
project structure here
It doesn't matter
You are right that you should run it on different servers for spring and react.
You can proxy your api request to the backend to avoid CORS issue.
Copy this to your src/setupProxy.js in your create-react-app. More info here
const proxy = require("http-proxy-middleware");
module.exports = app => {
app.use(
proxy("/api", {
target: "http://jsonplaceholder.typicode.com",
pathRewrite: { "^/api": "" },
changeOrigin: true
})
);
};
Then you can proxy request to your backend using /api prefix. Example i can do something like fetch('/api/users') in my frontend react app

Ktor App's Main Method Not Called When Deployed to AppEngine

Issue
The Ktor application's main method is not called when deployed to AppEngine. In the applications's main method is logic to retrieve content from an API request based on a Timer and save that information to a Firestore database which a client consumes.
This logic currently works when deployed in a Jar to AppEngine. However, implementing this with Ktor would save deploy time and help future proof the backend service if endpoints are required.
Expected
The Ktor application's main method is called once the app is deployed to AppEngine similar to how an application's main method is called when ran in IntelliJ.
Actual
The main method is only called once the app's hosted route is called.
ie: https://[yourProjectName].appspot.com
Setup
Main Method
import io.ktor.application.Application
fun Application.main() {
// App logic here.
}
build.gradle
buildscript {
ext.kotlin_version = '1.3.10'
ext.ktor_version = '1.0.0'
ext.appengine_version = '1.9.60'
ext.appengine_plugin_version = '1.3.4'
ext.junitJupiterVersion = '5.0.3'
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.google.cloud.tools:appengine-gradle-plugin:$appengine_plugin_version"
classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.3'
}
}
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.2.51'
}
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'war'
apply plugin: 'com.google.cloud.tools.appengine'
sourceSets {
main.kotlin.srcDirs = [ 'src/main/kotlin' ]
}
sourceCompatibility = 1.8
repositories {
jcenter()
mavenCentral()
maven { url "https://kotlin.bintray.com/ktor" }
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "io.ktor:ktor-server-servlet:$ktor_version"
implementation "io.ktor:ktor-html-builder:$ktor_version"
providedCompile "com.google.appengine:appengine:$appengine_version"
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
implementation 'io.reactivex.rxjava2:rxjava:2.1.1'
implementation 'com.google.firebase:firebase-admin:6.3.0'
implementation 'com.google.apis:google-api-services-youtube:v3-rev204-1.23.0'
testCompile group: 'junit', name: 'junit', version: '4.12'
// JUnit Jupiter API and TestEngine implementation
testCompile("org.junit.jupiter:junit-jupiter-api:${junitJupiterVersion}")
testRuntime("org.junit.jupiter:junit-jupiter-engine:${junitJupiterVersion}")
testCompile("org.assertj:assertj-core:3.10.0")
// To avoid compiler warnings about #API annotations in JUnit code
testCompileOnly('org.apiguardian:apiguardian-api:1.0.0')
}
kotlin.experimental.coroutines = 'enable'
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
task run(dependsOn: appengineRun)
appengine {
deploy {
version = 'media-staging-1201181257pm'
}
}
src/main/resources/application.conf
ktor {
application {
modules = [ InitializationKt.main ]
}
}
src/main/webapp/WEB-INF/
appengine-web.xml
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<threadsafe>true</threadsafe>
<runtime>java8</runtime>
</appengine-web-app>
web.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<servlet>
<display-name>KtorServlet</display-name>
<servlet-name>KtorServlet</servlet-name>
<servlet-class>io.ktor.server.servlet.ServletApplicationEngine</servlet-class>
<!-- path to application.conf file, required -->
<init-param>
<param-name>io.ktor.config</param-name>
<param-value>application.conf</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>KtorServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Thank you to Gabriel Machado on Kotlin Slack for answering this.
Gabriel recommends using a Cron Job as opposed to a Timer Task because there may be issues with a Timer thread based on scaling type.
GAE probably expects your app to look like a Java app (e.g., a Java style "main", not a Kotlin style "main").
Look at this for more info on how to do this: How to run Kotlin class from the command line?

App engine SDK not accessible in Gradle app engine project

My build.gradle:
buildscript { // Configuration for building
repositories {
jcenter() // Bintray's repository - a fast Maven Central mirror & more
mavenCentral()
}
dependencies {
classpath 'com.google.cloud.tools:appengine-gradle-plugin:+' // latest App Engine Gradle tasks
}
}
repositories { // repositories for Jar's you access in your code
maven {
url 'https://maven-central.storage.googleapis.com' // Google's mirror of Maven Central
// url 'https://oss.sonatype.org/content/repositories/snapshots' // SNAPSHOT Repository (if needed)
}
jcenter()
mavenCentral()
maven {
url "s3://my.private.repo.com/maven/releases"
credentials(AwsCredentials) {
accessKey AWS_ACCESS_KEY
secretKey AWS_SECRET_KEY
}
}
}
apply plugin: 'java' // standard Java tasks
apply plugin: 'war' // standard Web Archive plugin
apply plugin: 'com.google.cloud.tools.appengine' // App Engine tasks
dependencies {
providedCompile group: 'javax.servlet', name: 'servlet-api', version:'2.5'
compile 'com.google.appengine:appengine:+'
compile 'com.stripe:stripe-java:3.6.0'
compile 'javax.mail:mailapi:1.4.3'
}
appengine { // App Engine tasks configuration
run { // local (dev_appserver) configuration (standard environments only)
port = 8080 // default
}
deploy { // deploy configuration
stopPreviousVersion = true // default - stop the current version
promote = true // default - & make this the current version
}
}
group = 'com.example.appengine' // Generated output GroupId
version = '1.0-SNAPSHOT' // Version in generated output
sourceCompatibility = 1.7 // App Engine Standard uses Java 7
targetCompatibility = 1.7 // App Engine Standard uses Java 7
The Stripe and JavaMail JARs appear to be downloaded just fine. But when I run compileJava I get other errors:
/path/to/eclipse-workspaces/google-eclipse-projects/myproject/src/main/java/com/package/ChargeStripeServlet.java:3: error: package com.google.appengine.api.taskqueue.TaskOptions does not exist
import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl;
...
It appears that the App Engine SDK is not being downloaded, but I don't see any error message. I have installed the SDK locally, if that helps (although I suspect the JARS will just be downloaded anyway).
What you need to do is to add the following dependency:
compile 'com.google.appengine:appengine-api-1.0-sdk:+'
As you can see here 'com.google.appengine:appengine:+' is of type POM, hence does not carry any java classes, it's only a parent.

Resources