GAE : java.lang.NoClassDefFoundError: com/google/appengine/api/blobstore/BlobstoreServiceFactory - google-app-engine

Kindly help me with this. I am using blob store for saving images and it is working perfectly fine on my local environment. But when I deploy the same code the cloud it is throwing me the exception : java.lang.NoClassDefFoundError: com/google/appengine/api/blobstore/BlobstoreServiceFactory
I am using GAE 1.8.4

Most likely, appengine-api.jar is missing from your war/WEB-INF/lib/ folder.
If you use Eclipse, click on the Problems tab. You may see a warning saying that this jar is not available on a server. Right click on this warning, select QuickFix, select "Copy..." option. Or copy this jar to this directory manually.

In my case the required jar was inside the WEB-INF/lib folder but the error was still occuring... I found that this error was occuring because Jetty 9 was not done yet with class loading startup process while one of my initialization class was requiring BlobstoreService:
public class InitializeAppContextListener implements ServletContextListener {
private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
So I had to postpone instance variable initialization once context is fully loaded as follow:
public class InitializeAppContextListener implements ServletContextListener {
private BlobstoreService blobstoreService;
public void contextInitialized(ServletContextEvent event) {
blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
Then the webapp was able to start normally again. This new behavior appeared after we had upgraded from servlet-api 2.5 to 3.1 with JDK 1.8...

Related

IntelliJ - spring boot resources for ES6 configuration

I'm trying to make some simple project with AngularJs using ES6 with Traceur compiler and with Spring Boot as my backend. I already managed to configure my project so it works as I expected. I only have some problems with configuring IntelliJ to see my resources properly.
I put my static resources in src/main/resources/public and configure ResourceHandlerRegistry so that it redirects any unknown request to the main angular application file (I want to use html5 location mode, so it was necessary. I found working configuration in the second answer of this question Spring Boot with AngularJS html5Mode).
The error occurs when I import any of my ES6 modules:
import {appModule as app} from 'resources/app/main.js'; // <- here IntelliJ sees an error, it cannot find such file, but when I run the application it all works as expected
Here I uploaded my whole project: http://www.filedropper.com/spring-boot-test
Could anyone tell me what should I do to get rid of this error in IntelliJ or check what I've done wrong with my project?
btw. I use IntelliJ 14.
Edit:
I had error in StaticResourceConfigurator. It should be:
/* ... */
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/public/");
Instead of:
/* ... */
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/public/**").addResourceLocations("classpath:/resources/");
But it didn't solve my problem.

AspectJ advice not being detected in Spring application

I had an existing WAR with the following Spring (4.0.6.RELEASE) configuration:
<beans>
<context:annotation-config/>
<context:component-scan base-package="org.example"/>
</beans>
To this application I added the following annotation interface (copied verbatim):
package org.example;
#Documented
#Retention(RetentionPolicy.RUNTIME)
#Target({ ElementType.METHOD })
public #interface Logged {}
the following Aspect class (copied verbatim as well):
package org.example;
#Aspect
#Component
public class LoggingAspect
{
#Before("#annotation(Logged)")
public void before()
{
System.out.println("LoggingAspect.before()");
}
}
and the following batch processing class (copied verbatim):
package org.example;
#Component
public class Batch
{
#Logged
#Scheduled(fixedDelay = 100)
public void execute()
{
System.out.println("Batch.execute()");
}
}
The Spring configuration was then changed to:
<beans>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<context:annotation-config/>
<context:component-scan base-package="org.example"/>
<task:annotation-driven executor="executor" scheduler="scheduler"/>
<task:executor id="executor" pool-size="5"/>
<task:scheduler id="scheduler" pool-size="5"/>
</beans>
I was expecting to see the following messages on the console:
LoggingAspect.before()
Batch.execute()
However, I only see the second of these messages (that is, the aspect code is not being called).
I took out this code to a sample application and interestingly the two messages appear just fine in the sample app. I then compared every single file in the actual application with the sample and ensured that everything is exactly the same, including the class and file names. Yet, the aspect does not work in the actual application.
Upon turning on debug level logging in both applications, the sample application shows the following log message:
DEBUG org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory - Found AspectJ method: public void org.example.LoggingAspect.before()
but the actual application does not have this log message. This seems to indicate that the sample app detects the aspect method but the actual app does not. Both use the same Spring and AspectJ versions (4.0.6.RELEASE and 1.8.1 respectively). There are no errors in either log.
Spring instantiates LoggingAspect in both cases (gleaned from the logs).
I have also checked various JAR dependencies for the two apps and everything is the same, except that the actual app uses Spring ORM, Hibernate and EHCACHE JARs which the sample app does not.
Any pointers on what else should be checked will be useful.
Despite debugging the application for months, upgrading and degrading various Spring and AspectJ versions, the problem could not be resolved. Funnily enough, a sample application created out of the affected classes did not show any problems.
I had to finally circumvent the problem by specifying the aspect in the Spring configuration. The line:
<aop:aspectj-autoproxy proxy-target-class="true"/>
had to be changed to:
<aop:aspectj-autoproxy proxy-target-class="true">
<aop:include name="loggingAspect"/>
</aop:aspectj-autoproxy>
In this case loggingAspect is the default bean name assigned by the Spring framework to the instance of the bean class LoggingAspect. If the bean name is set to a different value, that value must be used with <aop:include />.

HttpServlet is a restricted class. Please see the Google App Engine

I am getting the following error when running a basic servlet on Eclipse Kepler (Windows 7) with GAE SDK 1.9.3 and Java 7:
java.lang.NoClassDefFoundError: javax.servlet.http.HttpServlet is a restricted class.
Please see the Google App Engine developer's guide for more details.
To reproduce:
install Java 7 SDK
install Kepler
install the GAE Eclipse plugin
create a GAE web project
implement the init method of a basic servlet and set load-on-startup to 1 in web.xml
then run the web application
I tried on 2 machines and I got the same error.
Create a servlet by extending HttpServlet, then Override doPost() and doGet() methods in your servlets. For example:
public class FileServlet extends HttpServlet {
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// do something
}
Well, I found what was wrong and it was my mistake. Sorry. When I installed Java 7, I specified a different directory for the JDK and the JRE, which is fine, except that I gave the same location twice and the files got mixed up. My GAE issue was a side effect.

Weld CDI on Google App Engine: Injection in servlet not happening

This is my first time working with GAE and I'm trying to get CDI working. Long story short: The #Inject field in my servlet is not getting injected (it's always null).
I'm working in Eclipse and debug the application on the local test server included in the GAE SDK (which is started by Eclipse as well). When I access the servlet on localhost, I get a null-pointer exception for someService. I've also output the value of someService to verify it is really null, which it is.
Edit: When I added a #Named("skldjfx") qualifier to the injection point, Weld complained the dependency is unsatisfied (in the validation phase), so that's a good sign. However, the field is still always null.
Servlet:
public class BlogServlet extends HttpServlet {
#Inject private SomeService someService;
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setContentType("text/plain");
resp.getWriter().println("Hello. " + someService.getSomeValue());
// \
// always null
}
}
SomeService class:
#ApplicationScoped
public class SomeService {
private String someValue = "some value";
public String getSomeValue() {
return someValue;
}
}
I've configured Weld's Listener in web.xml:
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>
The listener is properly loaded because it logs its initialization message: org.jboss.weld.environment.servlet.Listener contextInitialized.
I've included (an empty) beans.xml in both war/WEB-INF and war/META-INF. I also tried it without META-INF. Maybe beans.xml isn't processed? Other contents in the WEB-INF folder (such as web.xml) are processed properly.
How can I verify if beans.xml is processed and/or fix SomeService not getting injected?
It looks like it's not possible to use CDI with GAE, because GAE's Jetty fork ignores jetty-web.xml, which is needed to specify the BeanManager. See this link and this link. Really strange GAE is not supporting the use of CDI.
Note that these links are really old, but so far I haven't found any evidence to the contrary.
Anyway, my next step will be to use Google's own dependency injection framework Guice. Using it with GAE is described here. I'd prefer CDI though.

ClassNotPersistenceCapableException

I'm getting ClassNotPersistenceCapableException when trying to persist the following JDO class.
package com.xxx.cms.model;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Text;
#PersistenceCapable
public class Transaction {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
private String type;
#Persistent
private Text details;
#Persistent
private Company client;
#Persistent
private Carrier carrier;
#Persistent
private Company sender;
#Persistent
private Company recipient;
#Persistent
private Customs customs;
public Transaction(String type, Text details, Company client, Carrier carrier, Company sender, Company recipient, Customs customs){
this.setType(type);
this.setDetails(details);
this.setClient(client);
this.setCarrier(carrier);
this.setSender(sender);
this.setRecipient(recipient);
this.setCustoms(customs);
}
....
}
Then when I run the following:
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
pm.makePersistent(carrier);
pm.makePersistent(sender);
pm.makePersistent(recipient);
pm.makePersistent(client);
pm.makePersistent(cargo);
pm.makePersistent(finance);
pm.makePersistent(customs);
Transaction transaction = new Transaction(transactionType, transactionDetails, client, carrier, sender, recipient, customs);
pm.makePersistent(transaction);
} finally {
pm.close();
}
I get the following exception in the app logs:
org.datanucleus.jdo.exceptions.ClassNotPersistenceCapableException: The class "The class "com.xxx.cms.model.Transaction" is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data/annotations for the class are not found." is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data for the class is not found.
Any ideas why GAE is throwing this exception? The data from the other classes is persisted successfully as I can see it from the data viewer.
Quoting the exception
"The class "com.xxx.cms.model.Transaction" is not persistable. This means that it either hasnt been enhanced, or that the enhanced version of the file is not in the CLASSPATH (or is hidden by an unenhanced version), or the Meta-Data/annotations for the class are not found."
Which one of those possible options is true ?
I got this exact same exception when I started using Spring MVC in my GAE project. I was stuck, and almost decided to give up on GAE and Spring MVC until I found out that it was because I had been using the wrong version of a JAR. Quite a rookie mistake :(
I've put it down on my blog so that others can learn from this:
This is becuse trying DataNucleus is trying to register an identical plugin. If you see console by stopping you local server, it will show as -
DataNucleus Enhancer (version 1.1.4) : Enhancement of classes
Encountered a problem: Unexpected exception Please see the logs
[C:\Users\AppData\Local\Temp\enhance9016551549771995762.log] for
further information.
Then please check the log file ..
There error is highlighted as -
Caused by: org.datanucleus.exceptions.NucleusException: Plugin (Bundle) "org.datanucleus" is already registered. Ensure you dont have multiple JAR versions of the same plugin in the classpath.
The URL "file:/C:/VB/Softwares/eclipse-jee-mars-1-win32-x86_64/eclipse/plugins/com.google.appengine.eclipse.sdkbundle_1.9.30/appengine-java-sdk-1.9.30/lib/opt/tools/datanucleus/v2/datanucleus-core-3.1.3.jar" is already registered, and you are trying to register an identical plugin located at URL "file:/C:/VB/Softwares/eclipse-jee-mars-1-win32-x86_64/eclipse/plugins/com.google.appengine.eclipse.sdkbundle_1.9.30/appengine-java-sdk-1.9.30/lib/opt/user/datanucleus/v1/datanucleus-core-1.1.5.jar."
Thus same jar datanucleus-core having two version.
Now go to the path shown in error and Just delete the complete v1 folder as you have the latst v2 folder
with same latest jars and re-start your server, this will work....

Resources