AngularJS AJAX call to a servlet in JAVA - angularjs

My class in the project is under a package com.project.controller and the name of the servlet class is UpdateDatabaseController. The corresponding code of the web.xml is,
<servlet>
<servlet-name>UpdateDatabaseController</servlet-name>
<servlet-class>com.project.controller.UpdateDatabaseController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UpdateDatabaseController</servlet-name>
<url-pattern>/UpdateDB</url-pattern>
</servlet-mapping>
In the html page, I have a button that is calling a function, updateDatabase(). And the code of the script is:
$scope.updateDatabase = function(){
$http.get('/UpdateDB').success(function(data) {
alert("Controller hit");
});
};
Whenever I hit the button, the error in the browser log is displayed, that :
"NetworkError: 404 Not Found - http://localhost:8080/UpdateDB"
I want that on my button click, the POST method of the servlet class is invoked. But the error is fixed in the browser log. I am unable to solve this situation.

$scope.updateDatabase = function(){
$http.get('http://localhost/YourProject/UpdateDB').success(function(data) {
alert("Controller hit");
});
};
I had the same problem, and fixed it by adding http:// in front of the link.

you miss ProjectName in ur URL localhost:8080/ProjectName/UpdateDB

Related

How to resolve "You have not started an Objectify context" in JUnit?

I've got some Objectify test code running in JUnit and I'm getting this error:
java.lang.IllegalStateException: You have not started an Objectify context. You are probably missing the ObjectifyFilter. If you are not running in the context of an http request, see the ObjectifyService.run() method.
at com.googlecode.objectify.ObjectifyService.ofy(ObjectifyService.java:44)
at com.googlecode.objectify.impl.ref.LiveRef.<init>(LiveRef.java:31)
at com.googlecode.objectify.Ref.create(Ref.java:26)
at com.googlecode.objectify.Ref.create(Ref.java:32)
at com.netbase.followerdownloader.repository.DownloadTaskRepositoryImpl.create(DownloadTaskRepositoryImpl.java:35)
at com.netbase.followerdownloader.repository.DownloadTaskRepositoryImplTest.setUp(DownloadTaskRepositoryImplTest.java:45)
How do I resolve this for test code?
Jeff Schnitzer answered this here: https://groups.google.com/forum/#!topic/objectify-appengine/8HinahG7irg. That link points to https://groups.google.com/forum/#!topic/objectify-appengine/O4FHC_i7EGk where Jeff suggests the following quick and dirty workaround:
My #BeforeMethod starts an objectify context (ObjectifyService.begin())
My #AfterMethod closes the objectify context
Jeff suggests we use ObjectifyService.run() instead but admits it's more work.
Here's how my implementation looks:
public class DownloadTaskRepositoryImplTest {
// maximum eventual consistency (see https://cloud.google.com/appengine/docs/java/tools/localunittesting)
private final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()
.setDefaultHighRepJobPolicyUnappliedJobPercentage(100));
private Closeable closeable;
#Before
public void setUp() {
helper.setUp();
ObjectifyRegistrar.registerDataModel();
closeable = ObjectifyService.begin();
}
#After
public void tearDown() {
closeable.close();
helper.tearDown();
}
I also had this issue and noticed that I had not added the ObjectifyFilter to my web.xml
<filter>
<filter-name>ObjectifyFilter</filter-name>
<filter-class>com.googlecode.objectify.ObjectifyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ObjectifyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I also had to include Objectify and guava jars in my WEB-INF>lib directory and include them in my build path.
I was facing the same error and this solusion worked for me
I have an app based on Endpoints that uses Objectify. When I leave it with the default/automatic scaling, everything works great. Once I enable basic scaling, though, I get the following exception when executing the endpoint method:
[INFO] java.lang.IllegalStateException: You have not started an Objectify context. You are probably missing the ObjectifyFilter. If you are not running in the context of an http request, see the ObjectifyService.run() method.
[INFO] at com.googlecode.objectify.ObjectifyService.ofy(ObjectifyService.java:44)
[INFO] at com.myco.myapp.dao.datastore.OfyService.ofy(OfyService.java:62)
The good news is that this goes away when you enable RequestDispatcher
support in the web.xml file like so. I think this is a documentation
issue, then, but I didn't know if everyone would agree if I edited the
Wiki page directly. Here is the proposed web.xml entry, which worked
for me:
<filter>
<filter-name>ObjectifyFilter</filter-name>
<filter-class>com.googlecode.objectify.ObjectifyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ObjectifyFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Improving michael-osofsky answer, I add this to my ofy helper class
public static void registerDataModel() {
try {
factory().register(Profile.class);
} catch (Exception e){
e.printStackTrace();
}
}
and remplace
ObjectifyRegistrar.registerDataModel();
for this
OfyService.registerDataModel();
OfyService.java
public static void registerDataModel() {
try {
factory().register(Profile.class);
} catch (Exception e){
e.printStackTrace();
}
}
As Jeff Schnitzer says in the link provided by Michael Osofsky:
In your tests you should have some notion of a 'request' even if it is just conceptual. If "each test is a request by itself", then you can use #Before/#After in conjunction with ObjectifyService.begin() to demarcate the requests. However, this is probably not actually how your tests work - it isn't how my tests work.
He then goes on to say:
This would be prettier with JDK8 closures but the idea is straightforward - you're wrapping some unit of work in a context which represents a request. It would probably be smart to add even more context like authentication in that wrapper too.
I came up with the following implementation of his idea. With the solution below, you can ensure each call to a servlet handler gets a fresh Objectify session while still making your servlet handler calls in a single line of code. It also decouples your tests from explicitly worrying about Objectify, and allows you to add additional non-Objectify context around your servlet handlers.
My solution below works with Objectify 5.1.22. I tried using Objectify 6+, but I had problems that seem to be related to this.
First, define a custom Supplier that is able to capture the exceptions thrown by a servlet handler.
#FunctionalInterface
public interface ServletSupplier<T> {
T get()
throws ServletException, IOException;
}
Next, define a wrapper method that accepts your new custom Supplier as an input, and wrap the call to ServletSupplier.get() in a try-with-resources block that calls ObjectifyService.begin(). You must also register your entity classes before calling ServletSupplier.get().
public <T> T runInServletContext(ServletSupplier<T> servletMethod)
throws ServletException, IOException {
try (Closeable session = ObjectifyService.begin()) {
ObjectifyService.register(MyObj.class);
return servletMethod.get();
}
}
Finally, anywhere in your tests that you call the servlet handler you should do so using the wrapper method.
MyObj myObjPost = runInServletContext(() -> getServlet().doPost(request, response));
// Assert results of doPost call.
MyObj myObjGet = runInServletContext(() -> getServlet().doGet(request, response));
// Assert results of doGet call.
Just in case someone ends up here (as I originally did) looking up the same problem but for the ktor "main.kt" server instead of unit tests...
After looking at the ObjectifyFilter source code, I added
val closer = ObjectifyService.begin()
... real service here ...
closer.close()
around my actual servlet code and that fixed the problem.

How do you escape a . (full stop) or / so it doesn't change URL's meaning?

I have a Web API 2.0 service which defines a particular route:
/api/someEntityGroup/{entityName}
I'm calling this enpoint using Angular $resource service.
The problem is when user wants to provide an entity name with characters that have a specific meaning in URL:
404 Not found - . (full stop), /, +
400 Bad request - ?, :, &, %, *, <, >
And these are the ones I've encountered. There may be others that may be problematic as well and I'm not even aware of them (yet).
If I use window.escape() function these still don't work, but I mainly get 404 back (the only exception being * which still returns 400 Bad request).
My code
Angular resource creation:
.factory("entityResource", ["$resource", function() {
return $resource("/api/entities/:id", null, {
search: {
method: "GET",
url: "/api/entities/:name",
isArray: true
}
});
}]);
How I call it in my code:
entityResource.search({ query: scope.name }, function(data) {
...
});
My Api controller action:
[RoutePrefix("/api/entities")]
public class EntitiesController: ApiController
{
[Route("{searchQuery}")]
public IEnumerable<Interest> Get(string searchQuery)
{
return this.interestService.Search(searchQuery);
}
...
}
I can shed some light on your 404 Not found issue when using ., /, + characters.
The issue isn't with Angular but rather with Web API and the way it resolves routes. Urls that Web API interprets as being managed resources (e.g. static content, pages etc.) it will try to resolve independently.
Set the following in your web.config to disable this behavior and force WebAPI to run all requests through your modules:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
Just a warning - If your Web API is hosted together with something like MVC or a static website, the above is not recommended as it will force all managed resources (pages, MVC routes, content[css,js,images]) through your API modules and there will be a performance impact. However, if all the API is doing is serving resource routes I would recommend enabling the above.

GWT Upload fails to App Engine

I want to provide a file upload to Google App Engine with the "GWT Upload" (https://code.google.com/p/gwtupload/). During the upload I get an error. As UploadAction servlet I use the build in: gwtupload.server.gae.AppEngineUploadAction
The servlet is configured in the web.xml in the following way:
<context-param>
<!-- max size of the upload request -->
<param-name>maxSize</param-name>
<param-value>3145728</param-value>
</context-param>
<context-param>
<!-- Useful in development mode to slow down the uploads in fast networks.
Put the number of milliseconds to sleep in each block received in the server.
false or 0, means don't use slow uploads -->
<param-name>slowUploads</param-name>
<param-value>200</param-value>
</context-param>
<servlet>
<servlet-name>uploadServlet</servlet-name>
<!-- This is the default servlet, it puts files in session -->
<servlet-class>gwtupload.server.gae.AppEngineUploadAction</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>uploadServlet</servlet-name>
<url-pattern>*.gupld</url-pattern>
</servlet-mapping>
During upload the progress bar progresses some percentages and then shows the following error:
But there are no more details in the logs.
The error message shows the class gwtupload.server.gae.MemCacheFileItemFactory$CacheableFileItem with the method setHeader(). That's strange because I can't find the method in that class. What's happening here?
Edit:
This is basically all the custom code i use. On the server side i use the build in gwtupload.server.gae.AppEngineUploadAction servlet.
package com.uploadtest.client;
import gwtupload.client.IUploadStatus.Status;
import gwtupload.client.IUploader;
import gwtupload.client.IUploader.UploadedInfo;
import gwtupload.client.MultiUploader;
import gwtupload.client.PreloadedImage;
import gwtupload.client.PreloadedImage.OnLoadPreloadedImageHandler;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.RootPanel;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class GWTUploadTest2 implements EntryPoint {
// A panel where the thumbnails of uploaded images will be shown
private FlowPanel panelImages = new FlowPanel();
public void onModuleLoad() {
// Attach the image viewer to the document
RootPanel.get("thumbnails").add(panelImages);
// Create a new uploader panel and attach it to the document
MultiUploader defaultUploader = new MultiUploader();
RootPanel.get("default").add(defaultUploader);
// Add a finish handler which will load the image once the upload finishes
defaultUploader.addOnFinishUploadHandler(onFinishUploaderHandler);
}
// Load the image in the document and in the case of success attach it to the viewer
private IUploader.OnFinishUploaderHandler onFinishUploaderHandler = new IUploader.OnFinishUploaderHandler() {
public void onFinish(IUploader uploader) {
if (uploader.getStatus() == Status.SUCCESS) {
new PreloadedImage(uploader.fileUrl(), showImage);
// The server sends useful information to the client by default
UploadedInfo info = uploader.getServerInfo();
System.out.println("File name " + info.name);
System.out.println("File content-type " + info.ctype);
System.out.println("File size " + info.size);
// You can send any customized message and parse it
System.out.println("Server message " + info.message);
}
}
};
// Attach an image to the pictures viewer
private OnLoadPreloadedImageHandler showImage = new OnLoadPreloadedImageHandler() {
public void onLoad(PreloadedImage image) {
image.setWidth("75px");
panelImages.add(image);
}
};
}
In addition to that i added the following jars to my clath path:
log4j-1.2.17.jar
gwtupload-gae-0.6.6.jar
gwtupload-0.6.6.jar
commons-fileupload-1.3.jar
commons-io-2.4.jar
Also zipped my whole sample project and uploaded it here:
https://skydrive.live.com/redir?resid=60B826E451F52B4D!118&authkey=!ALa1n2mL2sRR0wU
Edit 2:
Like Manolo pointed out: I was using "commons-fileupload-1.3.jar" instead of "commons-fileupload-1.2.1.jar". Changing the jar fixed my problem!
The problem is in the version of the commons-fileupload you are using, change it to the version 1.2.1, which is the one pointed in the gwtupload documentation.
It should work with 1.2.2 as well, but to use 1.3 requires new methods (setHeaders) which are not in the UploadListeners provided with gwtupload.
You should change in your project the target java (JDK compliance) to 1.6, since it is the last one supported in GWT to avoid problems, although it runs in 1.7.

What is the URL to access a Hello-World Google Cloud Endpoint service?

I've generated a Google Endpoint AppEngine project in Eclipse by using the Generate AppEngine BackEnd as described in this blog post. What that post does not describe however, and which the official Google Docs describe poorly as well, is which URL I can access that service with locally?
The service generated has one generated endpoint called DeviceInfoEndpoint. The code is shown below as well as the code in web.xml. Which URL should I access listDeviceInfo() with given that I'm hosting on port 8888 locally? I've tried the following:
http://localhost:8888/_ah/api/deviceinfoendpoint/v1/listDeviceInfo => 404
http://localhost:8888/_ah/spi/deviceinfoendpoint/v1/listDeviceInfo => 405 GET not supported
http://localhost:8888/_ah/spi/deviceinfoendpoint/v1/DeviceInfo => 405 GET (...)
http://localhost:8888/_ah/spi/v1/deviceinfoendpoint/listDeviceInfo = > 405 GET(...)
Exerpt of DeviceInfoEndpoint.java:
#Api(name = "deviceinfoendpoint")
public class DeviceInfoEndpoint {
/**
* This method lists all the entities inserted in datastore.
* It uses HTTP GET method.
*
* #return List of all entities persisted.
*/
#SuppressWarnings({ "cast", "unchecked" })
public List<DeviceInfo> listDeviceInfo() {
EntityManager mgr = getEntityManager();
List<DeviceInfo> result = new ArrayList<DeviceInfo>();
try {
Query query = mgr
.createQuery("select from DeviceInfo as DeviceInfo");
for (Object obj : (List<Object>) query.getResultList()) {
result.add(((DeviceInfo) obj));
}
} finally {
mgr.close();
}
return result;
}
}
Web.xml:
<?xml version="1.0" encoding="utf-8" standalone="no"?><web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>SystemServiceServlet</servlet-name>
<servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
<init-param>
<param-name>services</param-name>
<param-value>com.example.dummyandroidapp.DeviceInfoEndpoint</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SystemServiceServlet</servlet-name>
<url-pattern>/_ah/spi/*</url-pattern>
</servlet-mapping>
</web-app>
API request paths should generally conform to the following:
http(s)://{API_HOST}:{PORT}/_ah/api/{API_NAME}/{VERSION}/
If you're interested in fetching/updating/deleting a specific resource, add an ID to the end. In your example, that suggests you should be querying:
http://localhost:8888/_ah/api/deviceinfoendpoint/v1/
(which maps to list when you're making a GET request).
In general, the APIs Explorer available at /_ah/_api/explorer makes it easy to discover and query these URLs.
You can controle the path by use:
#ApiMethod(path="listDeviceInfo", httpMethod = HttpMethod.GET)
public List<DeviceInfo> listDeviceInfo(){
//... definition
}
Then you can call that from you client as:
http://localhost:8888/_ah/api/deviceinfoendpoint/v1/listDeviceInfo
If you like send parameters then:
#ApiMethod(path="listDeviceInfo", httpMethod = HttpMethod.GET)
public List<DeviceInfo> listDeviceInfo(#Named("info") String info){
//... definition
}
http://localhost:8888/_ah/api/deviceinfoendpoint/v1/listDeviceInfo?info=holamundo

JavaEE default error handler servlet does not catch thrown errors

My problem is that the error handler code I register does not work on all errors. In my web.xml I registered my default error handler:
<servlet>
<servlet-name>ShowErrorHandlerServlet</servlet-name>
<servlet-class>tools.ErrorHandlerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ShowErrorHandlerServlet</servlet-name>
<url-pattern>/showerror</url-pattern>
</servlet-mapping>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/showerror</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/showerror</location>
</error-page>
<error-page>
<location>/showerror</location>
</error-page>
I am using Jersey to map rest request, so e.g. something like this:
#GET
#Path("/throwError")
public void testThrowUnauthException() {
// String s = null;
// s.toString();
// /*
// * this nullpointer exception would be caught correctly because of
// * <exception-type>java.lang.Exception</exception-type> in the web.xml
// */
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
The WebApplicationException is not caught and the default jetty 401 error page is shown:
HTTP ERROR 401
Problem accessing /v1/locations/throwError. Reason:
UNAUTHORIZED
Powered by Jetty
Registering
<error-page>
<error-code>401</error-code>
<location>/showerror</location>
</error-page>
does not work, but it works for 404 errors..
Does someone have an idea why this is happening? I need to catch all errors with the ErrorHandlerServlet to convert them to json error messages.
I think Jersey is overriding Jetty behaviour, so it is not taking the value on the XML. One way to solve it (maybe not the most elegant):
#Context HttpServletResponse res;
#GET
#Produces(MediaType.TEXT_HTML)
public String doFoo(){
try {
//Code that causes the error
} catch (Exception e) {
res.sendRedirect("/showError");
}
return "";
}
Another idea would be extending WebApplicationException and manage the responses yourself (probably the best)

Resources