Spring - RestController dispatcher - spring

in order to get my basic rest-api (only GET) working, i created this setup:
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>app</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
next i have this api controller:
package packagename.controller.api;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import packagename.model.Home;
#RestController
public class HomeApiController {
#RequestMapping("/api/home")
public Home greeting() {
return new Home(1, "asdas");
}
}
and the actual Home model:
package packagename.model;
public class Home {
private final long id;
private final String content;
public Home(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
When i create the war file and put it into the webapps folder of my tomcat server, i open "localhost:8080/webappname/api/home".
Next i get 404-error, but i have no idea why.
Anybody could help me with this setup?
Thanks and Greetings!

You've mixed spring boot with traditional web application.
RestController is enough and there is no need to specify a web.xml.
What you need is removing web.xml and add dependency spring-boot-starter-tomcat and marking it as provided and change packaging to war and configuring war plugin continue without a web.xml.
And document http://docs.spring.io/spring-boot/docs/1.4.0.BUILD-SNAPSHOT/reference/htmlsingle/#build-tool-plugins-maven-packaging could help.
Please let me know if any question.

Related

How to allow GET method for endpoint programmatically?

I am loading a .war file and add it as web app to the embedded Tomcat server.
#Bean
public EmbeddedServletContainerFactory servletContainerFactory() {
LOGGER.info("Adding web app");
return new TomcatEmbeddedServletContainerFactory() {
#Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
String appHome = System.getProperty(Environment.APP_HOME);
String targetFileName = "web-0.0.1-SNAPSHOT.war";
InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream(targetFileName);
LOGGER.info(System.getProperty("user.name"));
LOGGER.debug("Loading WAR from " + appHome);
File target = new File(Paths.get(appHome, targetFileName).toString());
try {
LOGGER.info(String.format("Copy %s to %s", targetFileName, target.getAbsoluteFile().toPath()));
java.nio.file.Files.copy(resourceAsStream, target.getAbsoluteFile().toPath(), StandardCopyOption.REPLACE_EXISTING);
Context context = tomcat.addWebapp("/", target.getAbsolutePath());
context.setParentClassLoader(getClass().getClassLoader());
} catch (ServletException ex) {
throw new IllegalStateException("Failed to add webapp.", ex);
} catch (Exception e) {
throw new IllegalStateException("Unknown error while trying to load webapp.", e);
}
return super.getTomcatEmbeddedServletContainer(tomcat);
}
};
}
This is working so far but if I access http://localhost:8080/web I am getting
2017-03-04 11:18:59.588 WARN 29234 --- [nio-8080-exec-2] o.s.web.servlet.PageNotFound : Request method 'GET' not supported
and the response
Allow: POST
Content-Length: 0
Date: Sat, 04 Mar 2017 10:26:16 GMT
I am sure all I have to do is to allow the GET method on /web and hopefully the static web content provided from the loaded war file will be accessible via web browser.
How/where can I configure the endpoint such that it allows GET requests?
I tried to introduce a WebController as described in this tutorial.
#Controller
public class WebController {
private final static Logger LOGGER = Logger.getLogger(WebController.class);
#RequestMapping(value = "/web", method = RequestMethod.GET)
public String index() {
LOGGER.info("INDEX !");
return "index";
}
}
In the log output I can see that this is getting mapped correctly:
RequestMappingHandlerMapping : Mapped "{[/web],methods=[GET]}" onto public java.lang.String org.ema.server.spring.controller.dl4j.WebController.index()
but it does not change the fact that I cannot visit the website.
I've also configured a InternalResourceViewResolver:
#Configuration
#EnableWebMvc
public class MvcConfiguration extends WebMvcConfigurerAdapter {
private final static Logger LOGGER = Logger.getLogger(MvcConfiguration.class);
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
LOGGER.info("configureViewResolvers()");
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setSuffix(".html");
registry.viewResolver(resolver);
}
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
web.xml
Since I configure everything in pure Java, this file does not define a lot:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Easy Model Access Server</display-name>
<listener>
<listener-class>org.ema.server.ServerEntryPoint</listener-class>
</listener>
<context-param>
<param-name>log4j-config-location</param-name>
<param-value>WEB-INF/classes/log4j.properties</param-value>
</context-param>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/web/*.html</url-pattern>
</servlet-mapping>
</web-app>
Reproduce
If you want to reproduce this you can simply checkout the entire code from github. All you need to do this:
mkdir ~/.ema
git clone https://github.com/silentsnooc/easy-model-access
cd easy-model-access/ema-server
mvn clean install
java -jar server/target/server-*.jar
This will clone, build and run the server.
The directory ~/.ema directory is required at the moment. It is where the WAR is being copied as the server starts.
My guess is that your web.xml maps any path to the Spring DispatcherServlet, something like:
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Because of <url-pattern>/</url-pattern> any request must be handled by a Spring controller, for this reason your static files are not served by Tomcat. Also a pattern like /*.html would have same effect.
If you have only a few pages you might add one or more mapping to the predefined default servlet for them, before the mapping of Spring (and also before Spring Security if you use it):
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>index.html</url-pattern>
</servlet-mapping>
You may also use <url-pattern>*.html</url-pattern> or, if your resources are under the web path and there are only static resources there: <url-pattern>/web/*</url-pattern>
Maybe all this is done instead in Java code in the org.ema.server.ServerEntryPoint that you have as a listener in web.xml
I think the mapping I wrote up in web.xml is done in your case in method getServletMappings of class org.ema.server.spring.config.AppInitializer, I changed it to use a more strict pattern /rest-api/* instead than /, not sure pattern is correct and everything else works, but now http://127.0.0.1:8080/index.html works
#Override
protected String[] getServletMappings() {
return new String[] { "/rest-api/*" };
}
as I see the url: http://localhost:8080/web is wrong.
You can try: http://localhost:8080/[name-of-war-file]/web

RestyGWT- custom url mapping for spring rest service

I have problem that my Spring Rest Controllers is mapped other way than RestyGWT would like.
My application is on: http://localhost:8080/restgwt/
According to web.xml:
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/action-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
My Spring service/controller listen on:
http://localhost:8080/restgwt/service/test
But my RestyGWT service calls this url:
http://localhost:8080/restgwt/restgwt/test
And I don't know how to tell to RestyGWT to change url. Please help.
I know that the simplest solution would be changing in web.xml file servlet url-pattern parameter
from: <url-pattern>/service/*</url-pattern>
to: <url-pattern>/restgwt/*</url-pattern>
but I would like to make RestyGWT to change it's behaviour.
Here paste some additional code:
TestService on GWT side
package pl.korbeldaniel.restgwt.client;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.fusesource.restygwt.client.MethodCallback;
import org.fusesource.restygwt.client.RestService;
public interface TestService extends RestService {
#GET
#Path("test")
public void getInfo(MethodCallback<TestPojo> test);
}
TestService on Spring side
package pl.korbeldaniel.restgwt.server;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
#RestController()
public class TestService {
#RequestMapping(value = "test", method = RequestMethod.GET)
public #ResponseBody TestEntity getInfo() {
TestEntity test = new TestEntity();
System.out.println("Hit server for getting _1");
return new TestEntity();
}
}
Reffering to the official documentation:
Configuring service root URLs
There are two ways to configure service root URLs which are appended with the #Path annotation property when building the final service URL. For single service root URL the Defaults.setServiceRoot(String) method can be used. When several services with different service roots are used the #Options annotation is equipped with the serviceRootKey property which can be set to read service root entries provided with the static ServiceRoots.add(String, String) method.
Defaults.setServiceRoot(new Resource( GWT.getModuleBaseURL()).resolve("../rest").getUri());
So my REST path for RestyGWT becomes http://domain-name/myGwtAppModuleName/rest/furtherPath
where furtherPath is javax.ws.rs #Path(..) value
Putting the line directly in GIN ClientModule failed with java.lang.UnsatisfiedLinkError: com.google.gwt.core.client.impl.Impl.getModuleBaseURL()Ljava/lang/String
To avoid error this I've wrapped it up
public class ClientModule extends AbstractPresenterModule {
#Override
protected void configure(){
//your installs and binds here
bind(RestyGwtConfig.class).asEagerSingleton();
}
}
public class RestyGwtConfig {
static {
Defaults
.setServiceRoot(new Resource( GWT.getModuleBaseURL()).resolve("../rest").getUri());
}
}

Spring Security with Java EE Restful Service

I have created a Java EE 6 restfull service and tried to integrate that with Spring Security. But, all the time I get different weird exceptions. Which doesn't make any sense or may be make sense but at least not for me.
Direction structure of my application is something like this:
com.security
UserDetailsSecurityConfig.java
com.service
ApplicationConfig.java
UserFacadeREST.java
com.config
AppConfig.java
My entities are auto generated so no error seems to be there. But, yes the three files seems fishy to me as UserFacadeREST is working fine when I don't integrate my application with Spring Security.
com.UserDetailsSecurityConfig.java
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class UserDetailsSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService( userDetailsService() );
}
#Override
protected void configure( HttpSecurity http ) throws Exception {
http
.httpBasic().and()
.sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS ).and()
.authorizeRequests().antMatchers("/**").hasRole( "USER" );
}
#Bean
public UserDetailsService userDetailsService() {
return new UserDetailsService() {
#Override
public UserDetails loadUserByUsername( final String username )
throws UsernameNotFoundException {
if( username.equals( "admin" ) ) {
return new User( username, "password", true, true, true, true,
Arrays.asList(
new SimpleGrantedAuthority("ROLE_USER" ),
new SimpleGrantedAuthority( "ROLE_ADMIN" )
)
);
} else if ( username.equals( "user" ) ) {
return new User( username, "password", true, true, true, true,
Arrays.asList(
new SimpleGrantedAuthority( "ROLE_USER" )
)
);
}
return null;
}
};
}
}
com.service.ApplicationConfig.java
#javax.ws.rs.ApplicationPath("webresources")
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(com.service.UserFacadeREST.class);
}
}
com.service.UserFacadeREST.java
#Stateless
#Path("user")
public class UserFacadeREST extends AbstractFacade<UpUser> {
#PersistenceContext(unitName = "PU")
private EntityManager em;
public UserFacadeREST() {
super(User.class);
}
#POST
#Override
#Consumes({"application/xml", "application/json"})
public void create(User entity) {
super.create(entity);
}
#GET
#Path("count")
#Produces("text/plain")
public String countREST() {
return String.valueOf(super.count());
}
}
com.config.AppConfig.java
#Configuration
#Import( UserDetailsSecurityConfig.class )
public class AppConfig {
#Bean
public ApplicationConfig applicationConfig() {
return new ApplicationConfig();
}
#Bean
public UserFacadeREST userRestService() {
return new UserFacadeREST();
}
}
In whole code I have made few changes for hit and trial. And currently, I am getting an exception.
java.lang.IllegalStateException: No WebApplicationContext found: no
ContextLoaderListener registered?
Before that I was getting another exception which was
WebSecurityConfigurers must be unique. Order of 100 was already used
I am not getting what I am doing wrong in integrating Spring Security with Java EE 6. I am new to Spring so may be I am doing a blunder which seems obvious to me.
My web.xml file is:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
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"
id="rest-sec" version="3.0">
<display-name>rest</display-name>
<!-- Spring security -->
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>etagFilter</filter-name>
<filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>etagFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
<!-- rest -->
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.labs.entities</param-value> <!-- won't find anything -->
</init-param>
<init-param>
<param-name>dispatchOptionsRequest</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
<!-- Disables servlet container welcome file handling. Needed for compatibility
with Servlet 3.0 and Tomcat 7.0 -->
<welcome-file-list>
<welcome-file />
</welcome-file-list>
</web-app>
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
You need to tell the filter where to look for your context (it's default is to look in a place that is not used by the servlet you created). In your filter add an init param:
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring</param-value>
</init-param>
WebSecurityConfigurers must be unique. Order of 100 was already used
Do you have 2 beans of type WebSecurityConfigurerAdapter? Or is your UserDetailsSecurityConfig being loaded twice?

jsf-spring : managedbean postconstruct not called

I'm rather learning by doing so it might be a stupid question but I couldn't find any answer.
I have an JSF application which worked well as used with simple JDBC.
Take an example of the "domain.xhtml", which had a table listing elements from a "DomainController" bean. It was all working great then we switched to JPA. That controller has to use services so it's declared as #Component and includes (#Autowired) services from there. It also works well EXCEPT that all my JSF injections (#ManagedProperty) are not injected anymore, my #PostConstruct is not called anymore either.
Is there something I missed, or is wrong with that manner to proceed ?
#ManagedBean
#Component
public class DomainController implements Serializable {
private static Logger log = Logger.getLogger(DomainController.class);
private static final long serialVersionUID = -2862060884914941992L;
private List<Domain> allItems;
private Domain[] selectedItem;
private SelectItem[] yesNoNull;
private DomainFilter filter = new DomainFilter();
#Autowired
private DomainService domainService;
#Autowired
private ValidationLookUpService validationLookUpService;
#Autowired
private ValidationService validationService;
#ManagedProperty("#{workspace.on}")
private boolean wsOn;
// #ManagedProperty("#{libraryVersionController.selectedItem.id}")
// private Integer selectedLibVersionID;
#ManagedProperty("#{libraryVersionController.selectedItem}")
private LibraryVersion selectedLibVersion;
#ManagedProperty("#{obsoleteEntry}")
private PObsoleteEntry pObsoleteEntry;
#ManagedProperty("#{validationFailedItemsController}")
private ValidationFailedItemsController validationFailedCont;
private Domain itemEdited;
private boolean persisted = false;
public DomainController() {
log.info("Creating metadata controller");
allItems = new ArrayList<Domain>();
// model for a yes/no/null column filtering
yesNoNull = new SelectItem[4];
yesNoNull[0] = new SelectItem("", "All");
yesNoNull[1] = new SelectItem("true", "yes");
yesNoNull[2] = new SelectItem("false", "no");
yesNoNull[3] = new SelectItem("null", "not yet validated");
}
#PostConstruct
public void test()
{
log.info("!!!");
log.info("WS is ... "+wsOn);
// NOT CALLED ANYMORE
}
...
My web.xml :
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets
and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name> <!-- indique le fichier de configuration pour Spring -->
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<context-param> <!-- to really skip comments in xhtml pages -->
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/faces-config.xml</param-value>
</context-param>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/app/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/spring/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<listener> <!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener> <!-- links JSF with spring -->
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener> <!-- parses JSF configuration -->
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<listener> <!-- vide le cache d’introspection Spring à l’arrêt du serveur. Ce listener n’est pas obligatoire mais conseillé -->
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
</web-app>
Thanks !
Correct me if I'm wrong but I don't see how I could just choose one, as Spring manages the back-end and JSF(+primefaces) the front-end.
I thought that the controller "could" have been the interface between the two, that's why I naively mixed them.
After some testing around your comments, I made my controller only use JSF and it injects the services using #ManagedBean (I didn't know either that using #ManagedBean it could inject a #Service Spring-managed bean) so that answers my question :)
Below is the corrected code working.
Thanks also for redirecting me in the right direction !
Controller
/**
* This is the controller for a Domain
*
*/
#ManagedBean
public class DomainController implements Serializable {
private static Logger log = Logger.getLogger(DomainController.class);
private static final long serialVersionUID = -2862060884914941992L;
private List<Domain> allItems;
private Domain[] selectedItem;
private SelectItem[] yesNoNull;
private DomainFilter filter = new DomainFilter();
#ManagedProperty(value="#{domainService}")
private DomainService domainService;
#ManagedProperty("#{workspace.on}")
private boolean wsOn;
#ManagedProperty("#{libraryVersionController.selectedItem}")
private LibraryVersion selectedLibVersion;
private Domain itemEdited;
private boolean persisted = false;
/**
* creates a list populated from the database
*/
public DomainController() {
log.info("Creating metadata controller");
allItems = new ArrayList<Domain>();
// model for a yes/no/null column filtering
yesNoNull = new SelectItem[4];
yesNoNull[0] = new SelectItem("", "All");
yesNoNull[1] = new SelectItem("true", "yes");
yesNoNull[2] = new SelectItem("false", "no");
yesNoNull[3] = new SelectItem("null", "not yet validated");
}
#PostConstruct
public void test()
{
Domain d = new Domain();
d.setDataset("will it work ?"); // yes
try {
domainService.saveOrUpdate(d);
} catch (DataModelConsistencyException e) {
e.printStackTrace();
}
}
// all functions
public DomainService getDomainService() {
return domainService;
}
public void setDomainService(DomainService domainService) {
this.domainService = domainService;
}
}
Service
public interface DomainService extends IVersionedServiceBase<Domain> {
public Domain saveOrUpdate(Domain d) throws DataModelConsistencyException;
public Domain getRelatedVariables(Domain d, VersionedObjectFilter versionedObjectFilter) throws DataModelConsistencyException;
StringAndError getVarNameAndKeyOrderForDomain(Domain d, VersionedObjectFilter versionedObjectFilter) throws DataModelConsistencyException;
}
Implementation of service
#Service("domainService")
#Transactional(readOnly = true)
public class DomainServiceImpl extends VersionedServiceBase<Domain> implements DomainService {
/**
* Private logger for this class
*/
#SuppressWarnings("unused")
private static final Logger log = Logger.getLogger(DomainServiceImpl.class.getName());
#Autowired
private DomainDao domainDao;
#Autowired
private VariableDao variableDao;
#Autowired
private DomainPurposeDao domainPurposeDao;
#Autowired
private DomainClassDao domainClassDao;
etc.

Can't find the request for url Observer

I am working with sample REST service with Apache CXF, But somehow I am not able to call the service. My implementation class is,
package com.ananth.lab.cfxrest.service;
import com.ananth.lab.cfxrest.vo.Address;
import com.ananth.lab.cfxrest.vo.Employee;
import org.springframework.stereotype.Service;
import javax.jws.WebService;
import javax.ws.rs.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
#Path("/cservice")
#Produces("application/xml")
public class EmployeeService {
#GET
#Path("/emp")
public Employee getEmployee() {
Address address1 = new Address();
address1.setCity("Chennai");
address1.setZip(63);
List<Address> list = new ArrayList<Address>();
Address address2 = new Address();
address2.setCity("Bangalore");
address2.setZip(49);
list.add(address1);
list.add(address2);
Employee emp = new Employee();
emp.setAddress(list);
emp.setEmployeeId("001");
emp.setEmployeeName("Ananth");
return emp;
}
}
My web.xml file is,
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Hello world REST service with apache cxf</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/beans.xml,WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
I deployed in Tomcat and the context path is "Lab". So I am trying to access the service like:
http://localhost:8080/Lab/cservice/emp
I am getting
No service was found.
I think you should make sure that your Employee class have a correctly "#" remark. just like below:
#XmlRootElement(name="cservice")
public class Employee (){
private String employeeId;
private String employeeName;
...
#XmlElement(name="employeeId")
public void setEmployeeId(String employeeId){
...
}
public String getEmployeeId(){
return this.employeeId;
}
#XmlElement(name="employeeName")
public void setEmployeeName(String employeeId){
...
}
public String getEmployeeName(){
return this.employeeName
}
...
...
}
and I suggest you to check WEB-INF/beans.xml & WEB-INF/applicationContext.xml.
Make sure your request url endpoint match your server endpoint.
combine url in web.xml and beans.xml result your endpoint

Resources