How to pass multiple parameter in Spring 3.0 AOP Advice method (#Before) using annotation? - spring-aop

I am preparing Spring AOP Demo Application.I am stuck.
My query is ..
How to pass multiple parameter in Spring 3.0 AOP Advice method (#Before) using annotation ?

from http://static.springsource.org/spring/docs/2.5.x/reference/aop.html check section 6.2.4.6.2
You can pass parameters following way
#Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation() &&" +
"args(account,..)")
public void validateAccount(Account account) {
// ...
}

Related

the difference between the Calling Object and the Target Object?

I'm learning Spring AOP and there are some termonolgies of this concept like Advice , PointCut , JoinPoint .. One of them is AOP Proxy and I found that a proxy is an intermediary object, introduced by the AOP framework, between the calling object and the target object. So my question is what is the difference between the Calling Object and the Target Object ?
Plese go through the reference document section : Understanding AOP Proxies
Following image depicts the concept of a proxy.
Consider a class TestService with method run() and a class Pojo with method foo(). Also consider Spring framework creates a proxy for Pojo .
#Component
public class TestService{
#Autowired
Pojo pojo;
public void run(){
pojo.foo()
}
}
Here the instance of TestService is the Calling Object and instance of Pojo is the Target object.

Apache Camel CXF difficulty calling an RPC/Encoded WSDL when updating list of elements

While not officially supported, with a few minor modifications to the WSDL I was able to successfully generate CXF Objects for the WSDL and get Camel CXF to talk to an RPC/Encoded WSDL endpoint. The code is incredibly simple and most request/responses work without issue except for attempting to send updates of a list of elements. Here is what the service expects:
<elements arrayType="UpdateElement">
VS here is what is being sent:
<elements>
I need to add the arrayType into the outgoing message. I looked into a number of ways of doing this:
1) An interceptor right before the SOAP message is sent by CXF then use XPath to add the element but I was not clear how to accomplish this using Apache Camel + Camel CXF. How to retrieve the CXF client from the Camel Context?
MyService client = ???
2) Fix it via WSDL? Is it possible to add this element to the WSDL so it is generated as a part of the CXF Objects? It is defined like this presently:
<message name="wsdlElementRequest">
<part name="elements" type="tns:UpdateElements" /></message>
'message' and 'part' come from http://schemas.xmlsoap.org/wsdl/.
Any ideas or suggestions would be appreciated. Thanks!
In case anyone ever stumbles on this with a similar issue, I figured it out myself. I was able to retrieve the CxfEndpoint via CamelContext:
camelContext.getEndpoint(endpointUrl, CxfEndpoint.class);
Then I was able to add the interceptor I created:
public class MyCxfInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
...
Using the CxfEndpoint methods:
cxfEndpoint.getOutInterceptors().add(new MyCxfInterceptor());
In my interceptor I also incorporated another interceptor, SAAJOutInterceptor, that converts the SOAP into an easy to work with object:
private List<PhaseInterceptor<? extends Message>> extras = new ArrayList<>(1);
public MyCxfInterceptor() {
super(Phase.USER_PROTOCOL);
extras.add(new SAAJOutInterceptor());
}
public Collection<PhaseInterceptor<? extends Message>> getAdditionalInterceptors() {
return extras;
}
The easy to work with SOAP message:
#Override
public void handleMessage(SoapMessage soapMessage) throws Fault {
SOAPMessage msg = soapMessage.getContent(SOAPMessage.class);
try {
SOAPBody soapBody = msg.getSOAPBody();
Then it was a simple matter of using XPATH to make the correction to the outgoing SOAP message.
private XPath xpath = XPathFactory.newInstance().newXPath();
...
NodeList nodeList = soapBody.getElementsByTagName("tagName");
for (int x = 0; x < nodeList.getLength(); x++) {
Node node = nodeList.item(x);
((Element) node).setAttribute("missingAttributeName", "missingAttributeValue");
}
I hope this helps anyone working with challenging SOAP services!
Credit to the blog which played a big part in enabling me to implement this solution: https://xceptionale.wordpress.com/2016/06/26/message-interceptor-to-modify-outbound-soap-request/

Camel REST (restlet) URL - confusing with path params

I'm using Camel Rest (with restlet component) and I have the following APIs:
rest("/order")
.get("/{orderId}").produces("application/json")
.param().dataType("int").type(RestParamType.path).name("orderId").endParam()
.route()
.bean(OrderService.class, "findOrderById")
.endRest()
.get("/customer").produces("application/json").route()
.bean(OrderService.class, "findOrderByCustomerId")
.endRest()
The problem is that the /order/customer doesn't works (see Exception below). The parameters for /customer comes from JWT...
java.lang.String to the required type: java.lang.Long with value
customer due Illegal characters: customer
I think that camel is confusing the ../{orderId} parameter with .../customer.
If I change the /customer for /customer/orders it's works.
The same idea in Spring Boot could have done with:
#RequestMapping("/order/{orderId}")
public Order getOrder(#PathVariable Long orderId) {
return orderRepo.findOne(orderId);
}
#RequestMapping("/order/customer")
public List<Order> getOrder() {
return orderRepo.listOrderByCustomer(1l);
}
Any idea about what's happening?
Try changing the order of your GET operations in the Camel Rest DSL. The restlet component has some issues in matching the best possible methods.
There is a couple of JIRA tickets related to this:
https://issues.apache.org/jira/browse/CAMEL-12320
https://issues.apache.org/jira/browse/CAMEL-7906

Apache Camel - How to set global component options

I'm using Camel with Spring Boot. I want to set "connectionTimeToLive" option for http component at global scope so that every use of the component will have the option. How can I do that?
After reading Camel test cases, I found out this solution using Custom Camel context configuration:
#Bean
CamelContextConfiguration contextConfiguration() {
return new CamelContextConfiguration() {
#Override
public void beforeApplicationStart(CamelContext context) {
HttpComponent http = context.getComponent("http4", HttpComponent.class);
http.setConnectionTimeToLive(5000);
}
#Override
public void afterApplicationStart(CamelContext camelContext) {
}
};
}
You have several options.
Add it to the camel registry and fetch it from there.
Add it as a Camel Exchange property.
Fetch it from a property file.
The way Camel works, you will have to configure this value in a property placeholder.
Also you can define endpoints in camel, instead of defining them straight away in the routes. (Eg: <endpoint id="bla" uri="foo" .. />). This way you can refer them in multiple places.
Also if you want to use this endpoint for multiple hosts, then consider passing things like host name, etc as a header. Eg: Exchange.HTTP_PATH
I am not sure whether Camel has any other Global config approach.
Cheers.

Best Approach for JPA lazy loading over Rest/AngularJS

Sorry for the general question, but is there an approach for still using JPA lazy loading of entities, when developing a restful AngularJS application.
In the old JSF days, it would all just work when a backing bean accessed the list.
I am using EclipseLink and Spring Data, with Jersey for the restful end points.
Regards
I
Generally you'd have to trigger the lazy loading of the entities prior the EntityManager being closed during the lifecycle of the request.
To do so, you can use the "Open EntityManager in View" pattern. Spring provides a Filter you can apply: OpenEntityManagerInViewFilter (read the docs here: http://docs.spring.io/spring/docs/4.1.0.RELEASE/javadoc-api/org/springframework/orm/jpa/support/OpenEntityManagerInViewFilter.html).
Alternatively, you can manually call getMyLazyCollection() on your JPA entity(ies) prior to serializing them to JSON.
I think the best course depends on following.
Are you able to retrieve the fully resolved entity i.e. all of its
components without adversely affecting performance ?
If the answer is Yes then go for resolving the full entity using JPA fetch option=eager.
I the answer is No. I would go for the following approach:-
1) Expose every lazy JPA component/association explicitly as a sub-resource.
e.g.
#Entity
public class Employee {
#Id
private long id;
...
#OneToOne(fetch=FetchType.LAZY)
#JoinColumn(name="ADDR_ID")
private Address homeAddress;
...
}
#Entity
public class Address{
}
2) Expose service as controller(although you can have them separated but I don't recommend)
#RequestMapping(value="/api/employee")
#Controller
public class EmployeeSvc
public Employee getEmployee(#PathVariable empID){
.....
}
#RequestMapping(value="{empID}/homeaddress")
public Address getHomeAddress(#PathVariable empID){
// will serve http://localhost:8080/api/employee/11111/homeaddress
return this.getEmployee(empID).getHomeAddress();
//make sure you are using 2nd Level cache - as you retrieve object twice
}
}

Resources