I have a service that has two classes and is very simple:
#ApplicationPath("/api")
public class HelloApplication extends Application {}
and
#Path("/hello-world")
public class HelloResource {
#GET
//#Produces("text/plain")
public Response hello() {
//return Response.ok().entity("This is JAX-RS").build();
return Response.ok().status(200).build();
//return "Hello, World!";
}
}
Commented lines are the ones that I tried to use. Every time I call "http://localhost:8080/api/hello-world" or "http://localhost:8080/api" the response is 404-Not Found. I use Tomcat 9.0.50.
What can be wrong with my usage of the classes or their calling from the outside?
The problem was - for some reason - in the usage of Tomcat. After moving to JBoss WildFly 24.0.0 the problem disappeared and the system started to work correctly.
If someone knows the reason of such an incompatibility - write a comment or an extra answer.
Related
I created a simple RESTful web service on the GlassFish server and run it according to this tutorial in the IntelliJ IDE. This runs fine based on the instruction provided. I have 2 additional questions,
a. The tutorial uses a service class provide below,
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
#Path("/helloworld")
public class HelloWorld {
#GET
#Produces("text/plain")
public String getClichedMessage() {
return "Hello World";
}
}
I can access that from the URL provided,
http://localhost:8080/AppointmentManager_war_exploded/helloworld
Afterward, I add a new class in the same directory,
#Path("/")
public class App {
#GET
#Produces("text/plain")
public String getMessage() {
return "Hello, Berlin";
}
}
I expected to see the message "Hello, Berlin" in the browser from the opening URL http://localhost:8080/AppointmentManager_war_exploded/, but, instead, I get the error provided,
HTTP Status 404 - Not Found
type Status report
messageNot Found
descriptionThe requested resource is not available.
GlassFish Server Open Source Edition 5.0
What is the issue here?
b. How do I change the part of URL AppointmentManager_war_exploded to something else, say, appointment etc? The artifact tab in the project setting is provided below,
I edited it, but, the change it not corresponded as expected.
I changed the project to maven build after the tutorial, but, the issue is not created for that. If someone interested, you can try too as it will take a minute to run.
Thank you.
First
I expected to see the message "Hello, Berlin" in the browser from the opening URL http://localhost:8080/AppointmentManager_war_exploded/, but, instead, I get the error provided
In MyApplication class that provided by tutorial you should also add your new class:
#ApplicationPath("/")
public class MyApplication extends Application{
#Override
public Set<Class<?>> getClasses() {
HashSet h = new HashSet<Class<?>>();
h.add(HelloWorld.class);
h.add(App.class); // Add your new class here
return h;
}
}
Then you will be able to see expected page on http://localhost:8080/AppointmentManager_war_exploded/
Second
How do I change the part of URL AppointmentManager_war_exploded to something else, say, appointment etc?
URL contains name of your artifact AppointmentManager_war_exploded. This artifact automatically copied to glassfish application directory. You can check glassfish\domains\domain1\applications\__internal.
Just change it just in project structure window here:
Update
Don't forget to change start URL in configuratin settings for app:
I am trying to create a Web service using JAX-WS. I do have a very basic Java project with the following:
EmployeeService .java
import javax.jws.WebMethod;
import javax.jws.WebService;
#WebService
public class EmployeeService {
#WebMethod
public String getEmployee(String id) {
return "Vlad Danila";
}
}
Exporter.java
import javax.xml.ws.Endpoint;
import services.EmployeeService;
public class Exporter {
public static void main(String[] args) {
Endpoint.publish("http://localhost:8080/hello",
new EmployeeService());
System.out.println("Successfull!");
}
}
Running the above will throw no error and print "Successfull!".
However, accessing http://localhost:8080/hello on browser gives This page isn’t working.
What am I missing?
I did an example with your code, and it works.. you have to add this to the browser to see
http://localhost:9999/ws/hello?wsdl
This is the url on my case. Then consume it with soap ui or another ws client.
The error you see its cause you are doing a get request on that url and not a soap request.
You don't give much context about what you are doing. JAX-WS is supposed to run in container. Do you run in container which is JEE compatible. See this tutorial, especially the last part:
https://docs.oracle.com/javaee/6/tutorial/doc/bnayn.html#gjyge
If you want something simple, I would recommend to make a spring-boot app, which will work out of the box for you. Forget about heavy JEE containers and try to run a simple spring-boot app which have integrated server inside the spring-boot app.
Here is a link to follow: https://spring.io/guides/gs/rest-service/
I know this is usually an issue that happens the other way around, so I am caught a little of guard here :D
I have built a user-management backend that provides a UI with data. When this architecture is deployed on our dev-server, everything works beautifully. However, as soon as I try to run the integration tests (which we do using a maven cargo tomcat) or if I use the war file in a local tomcat, the exception handlers aren't used at all. Spring simply displays a standard 500 response with the exception transformed into the body.
Perusing SO for similar issues has only resulted in the advice that I should use #EnableWebMVC, but that is neither applicable to what my backend is trying to accomplish, nor does it change anything.
How should I go about looking for the solution to this issue? Specifically, can I somehow observe if my controlleradvice is even scanned, and is there a reason why it might not be?
EDIT: These are the relevant files:
SpringConfiguration:
#Configuration
#ComponentScan(basePackageClasses = {UserManagementSpringConfiguration.class})
#EnableWebSecurity
public class UserManagementSpringConfiguration {
#Configuration
public static class ResourceMappingConfig implements WebMvcConfigurer {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/ui/*/usermanagement").setViewName("forward:/usermanagement-ui/index.html");
// registry.addViewController("/ui/*/*/generator/").setViewName("forward:/generator-ui/index.html");
registry.addViewController("/ui/*/usermanagement/*").setViewName("forward:/usermanagement-ui/index.html");
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// cache setting, otherwise fonts are not loaded in IE over https
CacheControl cacheControl = CacheControl.noCache().mustRevalidate();
registry.addResourceHandler("/ui/**/*").addResourceLocations("/usermanagement-ui/")
.setCacheControl(cacheControl);
}
}
}
ControllerAdvice:
#ControllerAdvice
public class CustomResponseEntityExceptionHandler {
public static final Logger LOG = EISLoggerFactory.getLogger(CustomResponseEntityExceptionHandler.class);
#PostConstruct
public void postConstruct() {
LOG.debug("CustomExceptionHandler loaded and ready for use");
}
#ExceptionHandler(PasswordMismatchException.class)
public final ResponseEntity<ErrorDetails> handlePasswordChangeMismatch(
PasswordMismatchException ex,
WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(
new Date(),
ex.getMessage(),
request.getDescription(false),
MessageKeys.mismatchedPassword);
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
}
}
It turns out that one of the modules that we wrote and that my project contains defines an ExceptionHandler for Throwable.class. On my machine, this ControllerAdvice is registered before my own ControllerAdvice, which causes Spring to look there first. Since Throwable fits the bill, Spring asks no further questions and just uses that handler.
The solution to my immediate problem was to add #Order(Ordered.HIGHEST_PRECEDENCE) to my ControllerAdvice. Since the exceptions I define within are quite specific, this will not cause any issues.
I have yet to find an explanation for why the order in which the two ControllerAdvice classes are registered is so consistently different between my machine and our dev server. Will update if I find anything. For now, I consider this issue to be answered.
This SO question was essential to solving this particular problem. Perhaps it helps someone in the future to link it here: Setting Precedence of Multiple #ControllerAdvice #ExceptionHandlers
Thanks to ValentinCarnu for pointing me to it!
I am working on a project based on Wildfly Swarm. The problem I currently have is that RESTeasy hides my index.html (and other html files) which are placed below /webapp since RESTeasy is listening on root level.
My Main Application:
#ApplicationPath("/")
public class XYZnlineApplication extends Application {
}
One of my resources:
#Path("protected/api/admin")
public class AdminResource {
#GET
#Path("public/api/offer/reduced")
#Produces("application/json")
public List<XYZ> getXYZ() {
...
}
#GET
#Path("protected/api/offer/full")
#Produces("application/json")
public List<XYZ> getAllXYZ() {
...
}
}
The thing is. If I start my wildfly swarm app and access one of the restendpoint above, everything works fine (e.g. http://localhost:8080/app/public/api/offer/reduced)
But if I d'like to access one of my html (e.g. login.html) files which are directly below /webapp, I get a 404 although the file is bundled correctly (e.g. on trying to access http://localhost:8080/app/login.html). So in my opinion what happens is that RESTeasy hides this html file cause it listens on root (/).
Since the first part of my url is the context (which is injected by a proxy) I can't set anything else than root (/) as ApplicationPath in my XYZApplication.
Do you have any idea on how I could solve this issue?
Thanks a lot in advance for your help.
You'll need to change the ApplicationPath to be something like "/services" or "/svc" or whatever works for you. Ultimately you need to partition the URL namespace between static resources and services. You don't need to worry about the context when specifying the ApplicationPath.
Major Edit:
Your comment really explains what's going on. I'm not sure what type of security you're using exactly but ultimately you likely need to have a filter of some sort in front of your services. I would have something like:
#Provider
#Priority(Priorities.AUTHENTICATION)
#PreMatching
public class AuthFilter implements ContainerRequestFilter {
#Context
private HttpServletRequest httpServletRequest;
#Context
private HttpServletResponse httpServletResponse;
#Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
if( containerRequestContext.getUriInfo().getPath().contains("/public/") )
return; // user is in public area - doesn't matter if they are authenticated
// guess at how to check if user is authenticated
if( httpServletRequest.getSession().get("user_is_ok") )
return;
httpServletResponse.sendRedirect("/login");
// or maybe
httpServletResponse.sendError(SC_UNAUTHORIZED);
}
}
Again, this is a bit of a guess but this is a pretty common way of handling your challenge.
I have a REST application that I swear worked yesterday. Today all paths, including the rest root, give a 404
Our REST root is defined here:
#ApplicationPath("/rest")
public class RestApplication extends Application
{
}
And my individual process is this:
#Stateless
#Path("/profileService")
public class ProfileSettingsComposite extends BaseComposite {
...
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/ContactPreferences")
#LoggerConfig(logType = "ERROR")
#Interceptors(value = { ExceptionHandler.class, MetricLogger.class, MethodLogger.class, MethodCacher.class })
public GetContactTypeComposite getContactPreferences(...
So I should be able to hit my webservice at
localhost:8080/ma-ejb/rest/profileService/ContactPreferences?blahparamblah
I have confirmed that the application is deployed to glassfish in the admin console. Anyone seen anything like this before?