Change name of Resteasy generated <collection> element to something else? - collections

<collection>
<Car>
<Car>
<Car>
</collection>
I would like to change the name of the tag to
I have no idea what I'm using--it's just Jboss 7.1.1 and a standard multimodule EAR maven setup. I should have RESTEasy included, with whatever JAXB provider they use.
#XmlElementWrapper annotation I have access to, but it does not work when I annotate the JAXRS service method "getCars". It has no effect on the xml output.
#Wrapped(element="cars") doesn't work b/c I can not seem to import the RESTEasy jax-rs jar. I added it into my pom.xml but it's not being picked up.
1) no idea if "jboss having RESTEasy included" means that I shouldn't even need to worry about importing another library just so that I can use the #Wrapped annotation.
2) Can I get by with the #XmlElementWrapper annotation for my purposes?
#GET
#Produces({MediaType.APPLICATION_XML})
#Path("/")
#XmlElementWrapper(name="cars")//I have access to this annotation but nothing happens
#Wrapped(element="cars")//eclipse doesn't know what this annotation means
public List<car> getCars();

You should be able to accomplish this by using the #Wrapped annotation.
To get this annotation into your project, try to add this artifact to your pom.xml:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>${resteasy.version}</version>
</dependency>
Another option is to create your own wrapper class:
#XmlRootElement(name="cars")
public class CarCollection {
#XmlElement(name="car")
private List<Car> articles = new ArrayList<Car>();
}
#GET
#Produces({MediaType.APPLICATION_XML})
#Path("/")
public CarCollection getCars();
Using just the #XmlElementWrapper annotation won't work.

Related

Add link to Spring Data REST Repository resource

I want to create a Link to a resource within a Spring Data REST Repository. I know that we can use ControllerLinkBuilder.linkTo method to create links to MVC controllers. As far is I understand Spring Data REST creates MVC controllers out of our Repository interfaces. But if I use
Instance createdInstance = instanceRepository.save(instance);
Link link = linkTo(InstanceRepository.class).slash(createdInstance.getId()).withSelfRel();
to create the link, I just get http://localhost:8080/2 (without the Repository path). Nothing changes if I specify the path explicitly with the #RepositoryRestResource at the Repository.
Of course I could just create the link explicitly, but I don't want to repeat myself.
public interface InstanceRepository extends CrudRepository<Instance, Long> {
}
Any advice on what I could do to resolve this issue without having to violate DRY principles?
Searching through the Spring Data REST source code I found the class RepositoryEntityLinks, which is used within the framework. It has a pretty nasty constructor, but (at least in my project) I am able to #Autowire the class.
In short the following code does the trick. Nevertheless I would be pleased to hear another persons more educated opinion on this!
Link link = entityLinks.linkToSingleResource(InstanceRepository.class, 1L);
If anyone is confused on how to piece it all together, you need to inject RepsitoryEntityLinks into your controller like so. Note no AutoWired is needed since spring will automatically inject the values if theres just the 1 constructor.
entityLinks.linkToCollectionResource(TodoRepository.class) is saying to spring - "give me the link to the TodoRepositories collection endpoint which would be something like localhost:8080/api/todos"
#RestController
#RequestMapping(value="/api")
public class PriorityController {
private RepositoryEntityLinks entityLinks;
public PriorityController(RepositoryEntityLinks entityLinks) {
this.entityLinks = entityLinks;
}
#GetMapping(value = "/priorities", produces = MediaTypes.HAL_JSON_VALUE)
public ResponseEntity<Resources<Priority>> getPriorities() {
Link link = entityLinks.linkToCollectionResource(TodoRepository.class);
resources.add(link);
return ResponseEntity.ok(resources);
}
}

Spring 4 AOP #Aspect isn't triggering for #RestController

I have created an Aspect which performs a basic id comparison to ensure that a user belongs to a the same group that created the entity being requested. I have had success attaching my aspect to #Service methods, but it doesn't make sense on the service layer, and I need it to be attached to #RestController methods instead. When I attempt to do this, everything seems good, but my Aspect never triggers, and the logs are silent.
pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
spring context
<context:annotation-config/>
<context:component-scan base-package="my.pkg"/>
<aop:aspectj-autoproxy/>
<aop:config proxy-target-class="true"/>
Aspect
#Aspect
#Component
public class MyAspect {
#Pointcut("within(#org.springframework.stereotype.Controller *)")
public void controller() {}
#Pointcut("within(#org.springframework.web.bind.annotation.RestController *)")
public void restController() {}
#Pointcut("args(java.security.Principal,..)")
public void principalArgPointcut() {}
#Around("(controller() || restController()) && principalArgPointcut()")
public Object validate(ProceedingJoinPoint point) throws Throwable {
doValidationBefore();
Object result = point.proceed();
doValidationAfter();
return result;
}
}
where "doValidationBefore()" and "doValidationAfter()" will throw an exception if validation fails.
And finally, my RestController
#RestController
#RequestMapping("/my-path")
public class MyController {
#RequestMapping(value = "/{entityId}", method = RequestMethod.GET)
public #ResponseBody
ResponseEntity<MyEntity> getEntityDetails(Principal principal, #PathVariable("entityId") Long entityId) {
return new ResponseEntity(HttpStatus.OK);
}
}
Some things to note:
This exact aspect works when I change the execution pattern to match services and place it in my service package.
The Aspect and the RestController are in the same context
I use IDEA IDE, and when I use the "navigate to advised methods" icon on the Aspect, the method I'm testing IS listed in the list of methods.
None of the methods listed in "navigate to advised methods" are working
Things I have tried:
I added 3 libraries to my pom.xml: org.aspectj:aspectjrt:1.8.6,
org.aspectj:aspectjtools:1.8.6, cglib:cglib:2.2.2. None of these made
any difference.
I tried defining my Aspect and PointCuts directly in the context xml and removing the annotations, no difference.
I have tried setting my execution pattern to apply to ALL methods, and it still did not trigger.
I tried adding an interface for my RestController, no change.
I would love some help here, as I've been trying to solve this for quite some time now. I know it must be possible.
As it turns out, my Aspect and my Controllers were NOT, in fact, in the same context.
While I believed my Controllers to be included in the context scanning of my web-context.xml, they were actually being scanned in WEB-INF/servlet-context.xml
Once I moved my Aspect configuration to WEB-INF/servlet-context.xml, my Aspect began to trigger as expected.
Thanks for all those who contemplated my problem.
Figure out for sure where your service is being configured in spring. If you have I there is an icon that you can click to navigate to the spring bean config. Then ensure that the aspect is configured in the same file.
If they are definitely defined in the same file, look next that the aop pointcut advice matches the method on which you're expecting it to fire. Again, Idea has an icon next to the pointcut that will navigate to matching methods.

Spring MVC Unit Test - how to use hamcrest matcher

I'm trying to write a simple test case for an MVC controller method.
I want to test the view name contains a string.
I think I need this version of the name matcher:
public ResultMatcher name(org.hamcrest.Matcher<? super String> matcher)
Taken from here:
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/web/servlet/result/ViewResultMatchers.html#name-org.hamcrest.Matcher-
But how do I use it? I can't work out the right syntax...
(syntax error on the Matchers.contains("web_tmpl") part of this expression:
this.mockMvc.perform(MockMvcRequestBuilders.get("/content/2"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.view().name(Matchers.contains("web_tmpl")))
;
You should add a static import for
import static org.hamcrest.Matchers.containsString;
and use
.andExpect(view().name(containsString("web_tmpl")))
if you're using maven the dependency is
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>

Specify run time parameter dependency in Unity

I have a class which needs a string as a parameter in its constructor but this parameter will be decided by the calling code. At the same point of time, the life time of this class has to be tied to per HTTP request. So, I created a custom PerWebRequestTimelineManager and used that for my target type in the config file. But since the string in the constructor has to be dynamically determined, I cannot use the ConstructorInjection via the config file. I can use an abstract factory to solve the problem of dynamic dependency, but I am not sure about the implementation: Can you check the code below and validate the approach. Specifically the RegisterType and Resolve calls seem a bit out of place though the successive Resolve calls across the application will be able to retrieve the same instance.:
public class PerformanceTracerFactory : IPerformanceTracerFactory
{
private readonly IPerformanceTracer tracer;
public IPerformanceTracer CreateInstance(string operationTitle)
{
_container.RegisterType<IPerformanceTracer, PerformanceTracer>(new InjectionConstructor(operationTitle));
return _container.Resolve<IPerformanceTracer>();
}
}
Relevant portion of config file:
<register type="IPerformanceTracer" mapTo="PerformanceTracer">
<lifetime type="PerWebRequest"/>
</register>
<register type="IPerformanceTracerFactory" mapTo="PerformanceTracerFactory"/>
I have another question. In case if the above way of configuring and injecting the dependency using code is correct, then I think I do not need the config entries. I can always use the suitable overload to push the custom lifetime manager. In case, I would want to achieve the same thing using only config file, then how do I code the solution?
If you use a container-based factory you don't have to register/resolve your IPerformanceTracer in each call.
Register the mapping IPerformanceTracer --> PerformanceTracer once in your config file and use a ParameterOverride when you resolve your interface.
public IPerformanceTracer CreateInstance(string operationTitle)
{
return _container.Resolve<IPerformanceTracer>(new ParameterOverride("nameOfTheParameterInTheConstructorOfPerformanceTracer", operationTitle);
}

Getting OSGi services from a bundle in Sling/CQ

I am using Day CQ. I want to store some data in a SQL Server DB, using the connection pool available in the Felix console. I can do this from a JSP, by using the "sling" object of type SlingScriptHelper defined in the defineObjects tag
sling.getService(DataSourcePool.class).
However, I want to use a servlet created in an OSGi bundle to handle requests from the client. The servlet doesn't have a defineObjects tag, so the "sling" object is not defined. I don't see a way to create a valid SlingScriptHelper object in my servlet, but it seems like it has to be possible.
Is there a way?
To get a service from a java OSGi component you don't need the SlingScriptHelper, you can either use the BundleContext.getService(...) method, or use SCR annotations to let SCR inject the service in your component.
As an example, you can look at how some components in Sling's Slingbucks sample use SCR annotations, the ConfirmedOrdersObserver class for example gets the SlingRepository in this way:
#Reference
private SlingRepository repository;
See http://felix.apache.org/site/apache-felix-maven-scr-plugin.html for the Maven plugin that handles these annotations.
You can use the BundleContext to get to the Service, by using the #getServiceReference and #getService methods. For example, if you were interested in the ResourceResolverFactory, you could get it like so:
BundleContext bundleContext = FrameworkUtil.getBundle(MyClass.class).getBundleContext();
ServiceReference factoryRef =
bundleContext.getServiceReference(ResourceResolverFactory.class.getName());
ResourceResolverFactory resolverFactory =
(ResourceResolverFactory) bundleContext.getService(factoryRef);
YourClass obj = this.getSlingScriptHelper().getService(yourclass.class);
obj.whatever();

Resources