Lately I started working on a tomcat web service again.
I hadn't touched it in a couple of weeks, and when I went to try something I'd written, I received a 404 error.
Stumped by what was going on, I eventually decided to just write a new hello world service to see what was going on, but then that 404's too.
I don't recall any updates to Tomcat, or having tweaked any settings, yet I can no longer access any methods I write for anything and it's confusing the hell out of me.
For example, the below classes should mean that http://localhost:8080/HelloWorld/API/Test/ should return a "Hello World" message, however it 404s and I have no idea what's going on.
context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/HelloWorld"/>
Application Config:
package main;
import java.util.Set;
import javax.ws.rs.core.Application;
#javax.ws.rs.ApplicationPath("API")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
addRestResourceClasses(resources);
return resources;
}
/**
* Do not modify addRestResourceClasses() method.
* It is automatically populated with
* all resources defined in the project.
* If required, comment out calling this method in getClasses().
*/
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(main.HWTest.class);
}
}
HWTest:
package main;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PUT;
import javax.ws.rs.core.MediaType;
#Path("/Test")
public class HWTest {
#Context
private UriInfo context;
/**
* Creates a new instance of HWTest
*/
public HWTest() {
}
/**
* Retrieves representation of an instance of main.HWTest
* #return an instance of java.lang.String
*/
#GET
#Path("/")
#Produces(MediaType.TEXT_PLAIN)
public String getText() {
//TODO return proper representation object
return "Hello world";
}
}
This definitely worked a few weeks ago, so I believe it might be something to do with a setting I accidentally tweaked, but I'm not sure as that wouldn't explain why new projects don't work either.
Related
so i have this jax-rs REST project and ive never used jax in my life.
what id like to do (probably not the right way) is when someone requests something from my api they should
type url.com/token/path/sub-path/
id like to collect the : /token/path/sub-path/ part, even better put it in an array like this :
[token,path,sub-path]
the project says i should use filters. i also have another issue where when im in the filter class i dont know how to output data, to either the web page or even my eclipse console.
package com.di3;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import com.di3.admin.AdminHandler;
public class LoginFilter implements ContainerRequestFilter{
#Context
#Override
public void filter(ContainerRequestContext request) throws IOException {
// TODO Auto-generated method stub
//do some token checking!
System.out.println(token);
}
}
thank you very much and sorry if the questions are silly or something.
The problem seems to be some poor error message.
I've created a dynamic web app project in eclipse and the runtime is TomEE+ 1.7.2
So this is the publisher
package study;
import java.io.IOException;
import java.net.InetSocketAddress;
import javax.ws.rs.ext.RuntimeDelegate;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class StandaloneJaxRsServer {
public static void main(String[] args) throws IOException {
HttpServer server = HttpServer.create(new InetSocketAddress(
"localhost", 8765), 8);
HttpHandler requestHandler = RuntimeDelegate.getInstance()
.createEndpoint(new JaxRSApplication(), HttpHandler.class); //<<<<< line 15
server.createContext("/jaxrs/", requestHandler);
server.start();
}
}
this is the app
package study;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath(value="/jaxrs")
public class JaxRSApplication extends Application{
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> set = new HashSet<>();
set.add(NotSingletonResource.class);
return set ;
}
//
// #Override
// public Set<Object> getSingletons() {
// Set<Object> set = new HashSet<>();
// set.add(new SingletonResource());
// return set ;
// }
}
and this is the resource
package study;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/notSingletonResource")
public class NotSingletonResource {
private volatile int counter = 0;
#GET
#Produces({MediaType.TEXT_HTML})
public String getHello() {
return "Not singleton resource " + counter++;
}
}
when I try to run StandaloneJaxRsServer.main() I get
Exception in thread "main" java.lang.IllegalArgumentException
at org.apache.cxf.jaxrs.impl.RuntimeDelegateImpl.createEndpoint(RuntimeDelegateImpl.java:104)
at study.StandaloneJaxRsServer.main(StandaloneJaxRsServer.java:15)
However, IllegalArgumentException does not tell much. What am I doing wrong?
The javadoc for the RuntimeDelegate interface states "Throws: IllegalArgumentException - if application is null or the requested endpoint type is not supported.' For a JAX-RS Application, I think you're supposed to use org.apache.cxf.jaxrs.JAXRSServerFactoryBean, and use the result of creating the endpoint to set up a server.
I won't accept my own answer, I just want to keep here some useful information just in case someone needs it.
TomEE+ does not have the libraries to make this work. Instead, what I've did was to remove all the TomEE+ dependencies from my eclipse project, then I've converted it to a maven project just to include this dependency according to #lmiguelmh answer to this question:
Latest Jersey example does not work
Then I've just added these jersey libraries
I'll wait a little bit more before accepting an answer here, because I really would like a better answer. I am following the steps described in the book "Java Web Services, Up and Running", so I think people will really need to know this information.
I am doing a simple Hello World example of java webservices, which is of document style from this link, he told that at step Number 3 , we will get an error message "Wrapper class com.mkyong.ws.jaxws.GetHelloWorldAsString is not found.
Have you run APT to generate them?".
But with out using wsgen, I am able to run my application with out any exception and able to see the output at client end. I am unable to find the reason , why didn't I get the error message?
Here is my code:
HelloWorld.java :
package com.XXX.ws;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
#WebService
#SOAPBinding(style = Style.DOCUMENT,use=Use.LITERAL)
public interface HelloWorld {
#WebMethod String getHelloWorldAsString(String name);
}
HelloWorldImpl.java:
package com.XXX.ws;
import javax.jws.WebMethod;
import javax.jws.WebService;
#WebService(endpointInterface = "com.XXX.ws.HelloWorld")
public class HelloWorldImpl implements HelloWorld {
#Override
public String getHelloWorldAsString(String name) {
// TODO Auto-generated method stub
return "Hello"+name;
}
}
Publisher.java
package com.XXX.endOP;
import javax.xml.ws.Endpoint;
import com.XXX.ws.HelloWorldImpl;
public class EndPublisher {
/**
* #param args
*/
public static void main(String[] args) {
Endpoint.publish("http://localhost:9999/ws/hello", new HelloWorldImpl());
System.out.println("Started");
}
}
After so much search found the following line
Using javac with JAX-WS annotation processor will generates the
portable artifacts used in JAX-WS services.
from this link
https://jax-ws.java.net/nonav/2.2.6/docs/ch04.html
When i try to use #Inject to inject my DAO class, in a manager to make it able to give a gson file to a current address i get this exception when i go to the specific web address.Can someone explain me what is the problem. I thought that the problem come maybe from the #Inject and it does not work correctly, but i am not sure.
java.lang.RuntimeException: org.apache.cxf.interceptor.Fault: Cannot obtain a free instance.; nested exception is:
javax.enterprise.inject.UnsatisfiedResolutionException: Api type [cinema.dao.ProjectionDAO] is not found with the qualifiers
Qualifiers: [#javax.enterprise.inject.Default()]
for injection into Field Injection Point, field name : projectionDAO, Bean Owner : [ProjectionManager, Name:null, WebBeans Type:DEPENDENT, API Types:[cinema.services.ProjectionManager,java.lang.Object], Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]] while invoking public java.util.Collection cinema.services.ProjectionManager.getAllProjections() with params [].
org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:116)
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:324)
org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:240)
org.apache.openejb.server.cxf.rs.CxfRsHttpListener.onMessage(CxfRsHttpListener.java:187)
org.apache.openejb.server.rest.RsServlet.service(RsServlet.java:53)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Code for the manager:
package cinema.services;
import java.util.Collection;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import cinema.dao.ProjectionDAO;
import cinema.model.Projection;
#Stateless
#Path("projection")
public class ProjectionManager {
#Inject
private ProjectionDAO projectionDAO;
#GET
#Produces("application/json")
public Collection<Projection> getAllProjections(){
return projectionDAO.getAllProjections();
}
}
Here is the ProjectionDAO:
package cinema.dao;
import java.util.Collection;
import javax.inject.Singleton;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import cinema.model.Projection;
import cinema.model.User;
#Singleton
public class ProjectionDAO {
#PersistenceContext
private EntityManager em;
public Collection<Projection> getAllProjections(){
return em.createNamedQuery("getAllProjections", Projection.class).getResultList();
}
public void addProjection(Projection projection){
em.persist(projection);
}
public Projection findProjectionByMovieTitle(String movieTitle){
try {
return em.createNamedQuery("getProjectionByMovieTitle", Projection.class)
.setParameter("movieTitle", movieTitle).getSingleResult();
} catch (NoResultException e){
return null;
}
}
public void buyTicket(Projection projection, User user){
Projection foundProjection = findProjectionByMovieTitle(projection.getMovieTitle());
if(foundProjection != null){
user.getCurrentProjections().add(projection);
int newFreeSpaces = foundProjection.getFreeSpaces() - 1;
foundProjection.setFreeSpaces(newFreeSpaces);
}
}
}
Projection is a simple model which give the movieTitle and start time of different projections in a cinema.
Your question doesn't state important information such as versions in use or how you're deploying, so I'm going to take a wild stab.
You're not including a beans.xml file in your deployment. I'm not sure though if you're deploying a WAR or a JAR file.
Assuming you have a properly placed beans.xml file, try swapping the #Singleton with an #ApplicationScope. This should more correctly discover your class.
I'm writing a (very) small SOAP web service using Glassfish. The code I have is below:
Milliseconds.java
package com.suture.self.ws;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.jws.soap.SOAPBinding.Use;
#WebService
#SOAPBinding(style = Style.DOCUMENT, use = Use.LITERAL)
public interface Milliseconds {
#WebMethod
String currentMilliseconds();
}
MillisecondsImpl.java
package com.suture.self.ws;
import javax.jws.WebService;
#WebService(endpointInterface = "com.suture.self.ws.Milliseconds")
public class MillisecondsImpl implements Milliseconds {
#Override
public String currentMilliseconds() {
return String.valueOf(System.currentTimeMillis());
}
}
MillisecondsEndpoint.java
package com.suture.self.ws;
import javax.xml.ws.Endpoint;
public class MillisecondsEndpoint {
public static void main(String[] args) {
Endpoint.publish("http://sutureself.com:9292/ws/milli", new MillisecondsImpl());
}
}
When I run this on my Glassfish server (through Eclipse), the admin console shows me the usual working ?wsdl and ?Tester endpoints, but not the one I have created. Hitting that url (http://sutureself.com:9292/ws/milli) in a browser also returns an "Unable to connect" error.
If I select "Launch", then I am shown two links (one for each http port in Glassfish), but these return a 404.
If I just try to hit the "Context Root" path, that also doesn't work. I need a point of entry and I just cannot find it.
What am I missing?
Please note! All the sutureself.com's in the above code are actually localhost, SO doesn't like you posting URL's with localhost evidently.
Any more information as to how my setup is configured will happily be added.
I also did an example in SOAP WS some time before but I have one doubt, why are you using Glassfish Server because you are deploying your WS by main method which will bind the address with your Service. I think for that no server is required.
Just follow these steps with eclipse for testing the WS-
Note: Please shutdown your Glassfish Server
1-Create a new java project(not dynamic web project)
2-Create a HelloWorld class in hello package
package hello;
import javax.jws.WebMethod;
import javax.jws.WebService;
#WebService
public class HelloWorld{
#WebMethod
public String method(String name)
{
return "hello " +name;
}
}
you don't need to make interface explicitly.
3:Now create a Publisher class to publish the WebService in hello package
package hello;
import javax.xml.ws.Endpoint;
public class Publisher {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Endpoint.publish("http://LH.com:9292/ws/milli", new HelloWorld());
}
}
Now you have bound your WS with http://LH.com:9292/ws/milli. Check it by http://LH.com:9292/ws/milli?wsdl or http://LH.com:9292/ws/milli?test