#XmlPath not working - spring

#XmlPath is not working.
Customer.java
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement(name= "Customer")
public class Customer {
private String CustomerId;
private String organizationCode;
private Extn extn;
private String organizationName;
private int reset;
private CustomerSchedulingPreferences customerSchedulingPreferences;
private ArrayList<RestrictedState> restrictedStateList;
#XmlAttribute
public String getCustomerId() {
return CustomerId;
}
public void setCustomerId(String customerId) {
CustomerId = customerId;
}
#XmlAttribute
public String getOrganizationCode() {
return organizationCode;
}
public void setOrganizationCode(String organizationCode) {
this.organizationCode = organizationCode;
}
#XmlElement(name="Extn")
public Extn getExtn() {
return extn;
}
public void setExtn(Extn extn) {
this.extn = extn;
}
#XmlPath("BuyerOrganization/#OrganizationName")
public String getOrganizationName() {
return organizationName;
}
public void setOrganizationName(String organizationName) {
this.organizationName = organizationName;
}
#XmlPath("BuyerOrganization/Extn/USSCORestrictedStateList")
#XmlElement(name = "USSCORestrictedState")
public ArrayList<RestrictedState> getRestrictedStateList() {
return restrictedStateList;
}
public void setRestrictedStateList(ArrayList<RestrictedState> restrictedStateList) {
this.restrictedStateList = restrictedStateList;
}
#XmlPath("BuyerOrganization/Extn/USSCORestrictedStateList/#Reset")
public int getReset() {
return reset;
}
public void setReset(int reset) {
this.reset = reset;
}
#XmlElement(name="CustomerSchedulingPreferences")
public CustomerSchedulingPreferences getCustomerSchedulingPreferences() {
return customerSchedulingPreferences;
}
public void setCustomerSchedulingPreferences(
CustomerSchedulingPreferences customerSchedulingPreferences) {
this.customerSchedulingPreferences = customerSchedulingPreferences;
}
}
Client.java
import javax.xml.transform.stream.StreamResult;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.oxm.Marshaller;
public class Client
{
public static void main(String[] args)throws IOException
{
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Marshaller marshaller = (Marshaller)context.getBean("jaxbMarshallerBean");
Customer customer=new Customer();
customer.setCustomerId("12345");
customer.setOrganizationCode("SUPPLY");
Extn extn = new Extn();
extn.setExtnBillCreditCode("000");
extn.setExtnBillSubscriptionId("132131");
customer.setExtn(extn);
RestrictedState resState1= new RestrictedState();
resState1.setOrgCode("952121");
resState1.setRestrictedStateCode("IN");
RestrictedState resState2= new RestrictedState();
resState2.setOrgCode("60325");
resState2.setRestrictedStateCode("IL");
ArrayList<RestrictedState> restrictedStateList = new ArrayList<RestrictedState>();
restrictedStateList.add(resState1);
restrictedStateList.add(resState2);
CustomerSchedulingPreferences custSchedPref = new CustomerSchedulingPreferences();
custSchedPref.setIsLineShipComplete("Y");
custSchedPref.setIsLineShipSingleNode("N");
custSchedPref.setOptimizationType("03");
customer.setCustomerSchedulingPreferences(custSchedPref);
customer.setRestrictedStateList(restrictedStateList);
marshaller.marshal(customer, new StreamResult(new FileWriter("customer.xml")));
System.out.println("XML Created Sucessfully");
}
}
applicationContext.Xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:oxm="http://www.springframework.org/schema/oxm"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/oxm
http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">
<oxm:jaxb2-marshaller id="jaxbMarshallerBean">
<oxm:class-to-be-bound name="com.javatpoint.Customer"/>
</oxm:jaxb2-marshaller>
</beans>
Structure of Output needed :
<Customer CustomerID="952121" OrganizationCode="SUPPLY" >
<Extn ExtnBillCreditCode="000" ExtnBillSubscriptionID="952121" />
<BuyerOrganization OrganizationName="Buy.com1" >
<Extn>
<USSCORestrictedStateList Reset="Y">
<USSCORestrictedState OrganizationCode="952121" RestrictedStateCode="IN"/>
</USSCORestrictedStateList>
</Extn>
</BuyerOrganization>
<CustomerSchedulingPreferences IsLineShipComplete="" IsLineShipSingleNode="" />
</Customer>
================================================================================
Please help me in resolving this:
Currently i am getting output like below :
<Customer organizationCode="SUPPLY" customerId="12345">
<CustomerSchedulingPreferences IsLineShipSingleNode="N" IsLineShipComplete="Y"/>
<Extn ExtnBillSubscriptionID="132131" ExtnBillCreditCode="000"/>
<reset>0</reset>
<USSCORestrictedState restrictedStateCode="IN" OrganizationCode="952121"/>
<USSCORestrictedState restrictedStateCode="IL" OrganizationCode="60325"/>
</Customer>

To leverage the #XmlPath extension you need to be using EclipseLink MOXy as your JAXB provider.
eclipselink.jar on your classpath
a jaxb.properties file in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html)
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Below is a link that will help set this up:
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/Spring

Related

JAXB #XmlValue Not Working

SampleMessage class:
#XmlRootElement(name = "SampleMessage")
#XmlAccessorType(XmlAccessType.FIELD)
public class SampleMessage {
#XmlAttribute
private String type;
#XmlElement(name = "Content", required = true)
private Content content;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Content getContent() {
return content;
}
public void setContent(Content content) {
this.content = content;
}
#XmlAccessorType(XmlAccessType.FIELD)
private static class Content {
#XmlValue
private String value;
#XmlAttribute(name = "name")
private String name;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
The Spring Boot - Rest Controller I have the follow method which basically just output the same XML form with what we passed, well supposed to be. This is just to check if it is parsing the XML properly.
#PostMapping(consumes = {MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_XML_VALUE})
public String handler(#RequestBody SampleMessage message) {
StringWriter writer = new StringWriter();
try {
JAXBContext jaxbContext = JAXBContext.newInstance(SampleMessage.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(message, writer);
} catch (JAXBException ex) {
System.out.println(ex.toString());
}
return writer.toString();
}
XML Sample 1: This is the initial XML sample I have:
<?xml version="1.0" encoding="UTF-8"?>
<SampleMessage type="TestType">
<Content name="TestContent">This is a sample content.</Content>
</SampleMessage>
Output (XML Sample 1): The output I get from the marshaller is this:
<?xml version="1.0" encoding="UTF-8"?>
<SampleMessage type="TestType">
<Content name="TestContent"/>
</SampleMessage>
Notice that there is no content text in the "Content" element that reads "This is a sample content". However, if I pass additional element Value inside "Content" element then it is able to output correctly.
XML Sample 2
<?xml version="1.0" encoding="UTF-8"?>
<SampleMessage type="TestType">
<Content name="TestContent"><Value>This is a sample content.</Value></Content>
</SampleMessage>
Correct Output
<?xml version="1.0" encoding="UTF-8"?>
<SampleMessage type="TestType">
<Content name="TestContent">This is a sample content.</Content>
</SampleMessage>
Any thoughts why is this?
This has resolved. Just noticed that this is a duplicate from my other post, sorry.
JAXB #XmlValue not able to get the text, Not generating empty XML element, and not able to read attribute

Spring JDBC update without commit

I have a simple table "employee" defined as:
create table employee (id int, name varchar2(40));
I want to write an application to insert values in it and commit only after all values are inserted. Here is my code:
Employee.java:
package com.empl;
public class Employee {
private int id;
private String name;
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
EmployeeDAO.java:
package com.empl;
import javax.sql.DataSource;
public interface EmployeeDAO {
public void setDataSource(DataSource dataSource);
public void create(int id, String name);
}
EmployeeJDBCTemplate.java:
package com.empl;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
public class EmployeeJDBCTemplate {
private DataSource dataSource;
private JdbcTemplate jdbcTemplateObject;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
this.jdbcTemplateObject = new JdbcTemplate(dataSource);
}
public DataSource getDataSource() {
return dataSource;
}
public void create(int id, String name) {
String SQL = "insert into employee (id, name) values (?, ?)";
jdbcTemplateObject.update(SQL, id, name);
}
}
MainApp.java:
package com.empl;
import java.sql.SQLException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String args[]) throws SQLException {
ApplicationContext context = new
ClassPathXmlApplicationContext("Beans.xml");
EmployeeJDBCTemplate employeeJDBCTemplate =
(EmployeeJDBCTemplate) context.getBean("employeeJDBCTemplate");
employeeJDBCTemplate.getDataSource().getConnection().
setAutoCommit(false);
employeeJDBCTemplate.create(1, "E1");
employeeJDBCTemplate.create(2, "E2");
}
}
Beans.xml:
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd ">
<bean id = "dataSource" class =
"org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name = "driverClassName" value =
"oracle.jdbc.driver.OracleDriver"></property>
<property name = "url" value =
"jdbc:oracle:thin:#localhost:1521/xe"></property>
<property name = "username" value = "sys as sysdba"></property>
<property name = "password" value = "pass"></property>
</bean>
<bean id = "employeeJDBCTemplate" class =
"com.empl.EmployeeJDBCTemplate">
<property name = "dataSource" ref = "dataSource"></property>
</bean>
</beans>
I executed the code but when I enter SQLPlus and type the rollback; command, the records are still in the table.
I saw related questions but nothing seems to work.

Apache cxf basic authentication

I have a running example of apache cxf but when I run this wsdl file provided by my code is not authenticated I don't know how to pass the username and password to soapui
The code is:
ORDER.JAVA
package demo.order;
public class Order {
private String customerID;
private String itemID;
private int qty;
private double price;
// Constructor
public Order() {
}
public String getCustomerID() {
return customerID;
}
public void setCustomerID(String customerID) {
this.customerID = customerID;
}
public String getItemID() {
return itemID;
}
public void setItemID(String itemID) {
this.itemID = itemID;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
package demo.order;
import javax.jws.WebService;
#WebService
public interface OrderProcess {
String processOrder(Order order);
}
package demo.order;
import javax.jws.WebService;
#org.apache.cxf.interceptor.InInterceptors (interceptors = {"demo.order.server.OrderProcessUserCredentialInterceptor" })
#WebService
public class OrderProcessImpl implements OrderProcess {
public String processOrder(Order order) {
System.out.println("Processing order...");
String orderID = validate(order);
return orderID;
}
/**
* Validates the order and returns the order ID
**/
private String validate(Order order) {
String custID = order.getCustomerID();
String itemID = order.getItemID();
int qty = order.getQty();
double price = order.getPrice();
if (custID != null && itemID != null && qty > 0 && price > 0.0) {
return "ORD1234";
}
return null;
}
}
_______________
package demo.order.client;
import demo.order.OrderProcess;
import demo.order.Order;
import org.apache.cxf.frontend.ClientProxy;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class Client {
public Client() {
}
public static void main(String args[]) throws Exception {
ClassPathXmlApplicationContext context
= new ClassPathXmlApplicationContext(new String[] {"demo/order/client/client-beans.xml"});
OrderProcess client = (OrderProcess) context.getBean("orderClient");
OrderProcessClientHandler clientInterceptor = new OrderProcessClientHandler();
clientInterceptor.setUserName("John");
clientInterceptor.setPassword("password");
org.apache.cxf.endpoint.Client cxfClient = ClientProxy.getClient(client);
cxfClient.getOutInterceptors().add(clientInterceptor);
Order order = new Order();
order.setCustomerID("C001");
order.setItemID("I001");
order.setQty(100);
order.setPrice(200.00);
String orderID = client.processOrder(order);
String message = (orderID == null) ? "Order not approved" : "Order approved; order ID is " + orderID;
System.out.println(message);
}
}
_____________________
package demo.order.client;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class OrderProcessClientHandler extends AbstractSoapInterceptor {
public String userName;
public String password;
public OrderProcessClientHandler() {
super(Phase.WRITE);
addAfter(SoapPreProtocolOutInterceptor.class.getName());
}
public void handleMessage(SoapMessage message) throws Fault {
System.out.println("OrderProcessClientHandler handleMessage invoked");
DocumentBuilder builder = null;
try {
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
Document doc = builder.newDocument();
Element elementCredentials = doc.createElement("OrderCredentials");
Element elementUser = doc.createElement("username");
elementUser.setTextContent(getUserName());
Element elementPassword = doc.createElement("password");
elementPassword.setTextContent(getPassword());
elementCredentials.appendChild(elementUser);
elementCredentials.appendChild(elementPassword);
// Create Header object
QName qnameCredentials = new QName("OrderCredentials");
Header header = new Header(qnameCredentials, elementCredentials);
message.getHeaders().add(header);
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
_________________________
CLIENTBEAN.XML
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<jaxws:client id="orderClient" serviceClass="demo.order.OrderProcess" address="http://localhost:8080/OrderProcess" />
</beans>
_______________________
package demo.order.server;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import demo.order.OrderProcess;
import demo.order.OrderProcessImpl;
public class OrderProcessServerStart {
public static void main(String[] args) throws Exception {
OrderProcess orderProcess = new OrderProcessImpl();
JaxWsServerFactoryBean server = new JaxWsServerFactoryBean();
server.setServiceBean(orderProcess);
server.setAddress("http://localhost:8787/OrderProcess");
server.create();
System.out.println("Server ready....");
Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting");
System.exit(0);
}
}
___________________________
package demo.order.server;
import javax.xml.namespace.QName;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
public class OrderProcessUserCredentialInterceptor extends AbstractSoapInterceptor {
private String userName;
private String password;
public OrderProcessUserCredentialInterceptor() {
super(Phase.PRE_INVOKE);
}
public void handleMessage(SoapMessage message) throws Fault {
System.out.println("OrderProcessUserCredentialInterceptor handleMessage invoked");
QName qnameCredentials = new QName("OrderCredentials");
// Get header based on QNAME
if (message.hasHeader(qnameCredentials )) {
Header header = message.getHeader(qnameCredentials);
Element elementOrderCredential= (Element) header.getObject();
Node nodeUser = elementOrderCredential.getFirstChild();
Node nodePassword = elementOrderCredential.getLastChild();
if (nodeUser != null) {
userName = nodeUser.getTextContent();
}
if (nodePassword != null) {
password = nodePassword.getTextContent();
}
}
System.out.println("userName retrieved from SOAP Header is " + userName);
System.out.println("password retrieved from SOAP Header is " + password);
// Perform dummy validation for John
if ("John".equalsIgnoreCase(userName) && "password".equalsIgnoreCase(password)) {
System.out.println("Authentication successful for John");
} else {
throw new RuntimeException("Invalid user or password");
}
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
_______________
I have these files and the program compile succesfully and creting the wsdl file
but its not working on soapui means username and password are null when requsting through soapui,
please suggest me how to overcome this problem of basic authentication
and how to pass the usename and password to soap ui
For Basic authentication in SOAP UI, navigate to your Request, single click on it will display a panel in the left bottom corner. Your config for BASIC Authentication should be something like this:
Add your username and password to the appropriate fields.
For your client I see you are using Spring. So jaxws:client provides username and password attributes for authentication. You can add them like this:
<jaxws:client id="orderClient"
serviceClass="demo.order.OrderProcess"
address="http://localhost:8080/OrderProcess"
username="yourUsername"
password="yourPassword"/>

Load-time weaving with AspectJ in the Spring Framework Private methods

I have built an application to test injecting log information (Entering and Exiting) around classes. I have built it using spring and used the following example for building it.
http://static.springsource.org/spring/docs/2.5.5/reference/aop.html#aop-aj-ltw
It works great now but I have 2 issues:
Private methods are not included when the log is weaved around the method. Is there a setting in the xml settings for spring to allow private methods to be weaved or is there another way around this?
I have to include all packages that are to be weaved in the META-INF/aop.xml for this to be able to work. Is there a setting to be used so that the log information can be weaved for all classes created in the project without having to add the package name to the aop.xml.
Below I have included all code and xml that is used. As I said all is working fine except the 2 issues above. Please assist me.
app.java
package se.jpab.application;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;
#Service
public class App
{
public static void main( String[] args )
{
ApplicationContext appContext = new ClassPathXmlApplicationContext( new String[] { "spring.xml" });
Client client = (Client) appContext.getBean("client");
Location clientLocation = (Location) appContext.getBean("location");
// Set all values
clientLocation.setAdress1("Adress 1");
clientLocation.setAdress2("Adress 2");
clientLocation.setBox("N/A");
clientLocation.setCity("City of Dallas");
client.setName("John Doe");
client.setUrl("http://www.url.com");
client.setLocation(clientLocation);
// Print out all values
System.out.println(client.getName());
System.out.println(client.getUrl());
System.out.println(client.getLocation().getAdress1());
System.out.println(client.getLocation().getAdress2() + " " + client.getLocation().getCity());
}
}
Client.java
package se.jpab.application;
import org.springframework.stereotype.Service;
#Service
public class Client {
String name;
String url;
Location location;
//Constructors
public Client(String custName, String custUrl, Location custLocation){
name = custName;
url = custUrl;
location = custLocation;
}
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
public Client(){
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
printThis(name);
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public void printThis(String inStr) {
System.out.println("PRIVAT METOD");
System.out.println("Inkommand sträng --> " + inStr);
}
}
Location.java
package se.jpab.application;
import org.springframework.stereotype.Service;
#Service
public class Location {
String city;
String adress1;
String adress2;
String box;
//Constructors
public Location (String city, String adress1, String adress2, String box){
this.city = city;
this.adress1 = adress1;
this.adress2 = adress2;
this.box = box;
}
public Location (){
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getAdress1() {
return adress1;
}
public void setAdress1(String adress1) {
this.adress1 = adress1;
}
public String getAdress2() {
return adress2;
}
public void setAdress2(String adress2) {
this.adress2 = adress2;
}
public String getBox() {
return box;
}
public void setBox(String box) {
this.box = box;
}
}
aop.xml
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver options=" -showWeaveInfo">
<!-- only weave classes in our application-specific packages -->
<include within="se.jpab.application.*"/>
<include within="se.jpab.aspect.*"/>
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="se.jpab.aspect.InjectLogg"/>
</aspects>
</aspectj>
Aspect
package se.jpab.aspect;
import java.util.Arrays;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class InjectLogg {
private static final Log fallbackLogger = LogFactory.getLog(InjectLogg.class);
#Around("execution(public * se.jpab.application..*.*(..))")
public Object profile(ProceedingJoinPoint pjp) throws Throwable {
Object invoker = pjp.getThis();
Log logger;
logger = LogFactory.getLog(getClassNameFrom(invoker.getClass()));
// Start injecting logg messages on entering a method.
logger.info("ENTERING: (" + pjp.getSignature().getName() + ")");
try {
logger.info("ARGUMENTS: " + Arrays.toString(pjp.getArgs()) + ")");
} catch (NullPointerException e) {
logger.info("ARGUMENTS: No arguments");
}
try {
// proceed to original method call
Object result = pjp.proceed();
// Injecting exiting messages after method is finished
logger.info("RESULT: " + result);
logger.info("EXITING: (" + pjp.getSignature().getName() + ")");
// Return the result of the method we are logging
return result;
} catch (IllegalArgumentException e) {
// same with ThrowsAdvice
logger.info("Exception. Throws IllegalArgumentException");
throw e;
}
}
private String getClassNameFrom(Class invokerClassName) {
// Function that ....... To be continued JP
// Add check for that string contains $$ and se.goteborg if not then
// return fallback logger class.
String[] classNameParts = invokerClassName.getName().split("$$");
int positionOfPackageName = classNameParts[0].indexOf("se.jpab");
String className = classNameParts[0].substring(positionOfPackageName);
return className;
}
}
Spring configuration (spring.xml)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<aop:aspectj-autoproxy proxy-target-class="true"/>
<context:load-time-weaver/>
<context:annotation-config />
<context:component-scan base-package="se.jpab"/>
</beans>
Your first question:
Private methods are not included when the log is weaved around the
method. Is there a setting in the xml settings for spring to allow
private methods to be weaved or is there another way around this?
If you want to weave private methods, use full AspectJ and therein a privileged aspect, not Spring AOP. The Spring manual says:
If your interception needs include protected/private methods or even
constructors, consider the use of Spring-driven native AspectJ weaving
instead of Spring's proxy-based AOP framework. This constitutes a
different mode of AOP usage with different characteristics, so be sure
to make yourself familiar with weaving first before making a decision.
Your second question:
I have to include all packages that are to be weaved in the
META-INF/aop.xml for this to be able to work. Is there a setting to be
used so that the log information can be weaved for all classes created
in the project without having to add the package name to the aop.xml.
You can catch a package an all its subpackages with the .. syntax, e.g. se.jpab.application..* or even se.jpab..*. You can also combine several conditions with boolean operators. See the AspectJ documentation for examples.

Spring doesn't inject my bean

what's wrong with my accounting example? The Calculator bean doesn't get injected into the Accoount. There is a null-pointer-exception in the deposit method because calculator is null.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath:/META-INF/spring/context.xml")
public class DITestJavaTest extends Assert {
#Test
public void diTest() {
Account account = new Account(500);
account.deposit(500);
assertEquals("balance is 1000", 1000, account.getBalance(), 0.0001);
}
}
public class Account {
#Autowired
private ICalculator calculator;
private double balance;
public Account() {
balance = 0;
}
public Account(double balance) {
this.balance = balance;
}
public void deposit(double amount) {
balance = calculator.add(balance, amount);
}
public void withdraw(double amount) {
balance = calculator.subtract(balance, amount);
}
public double getBalance() {
return balance;
}
}
#Component
public class Calculator implements ICalculator {
#Override
public double add(double summand1, double summand2) {
System.out.println("Main implementation with " + Calculator.class.getName() + "addition");
BigDecimal result = round(summand1 + summand2);
return result.doubleValue();
}
#Override
public double subtract(double minuend, double subtrahend) {
System.out.println("Main implementation with " + Calculator.class.getName() + "subtraction");
BigDecimal result = round(minuend - subtrahend);
return result.doubleValue();
}
private BigDecimal round(double amount) {
return new BigDecimal(amount).setScale(2, BigDecimal.ROUND_HALF_UP);
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="org.example.banking" />
<context:annotation-config />
</beans>
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath:/META-INF/spring/context.xml")
public class DITestJavaTest extends Assert {
#Autowired
Account account
#Test
public void diTest() {
account.deposit(500);
account.deposit(500);
assertEquals("balance is 1000", 1000, account.getBalance(), 0.0001);
}
}
Don't initialize account in your test. This way it's not managed by Spring and the Calculator is never injected
And as suggested, annotate Account with #Component
You need to anotate Account class as well to tell spring that it contains annotated member.
Somethng like
#Component
public class Account { ... }

Resources