I am creating a new payment application. What I have is a client application that user selects price, enter its authentication information and then client creates and iso 8583 message and send this data to a bank server.
According to my researches, I can use jPOS for emulating bank server. Actually I need a server for getting the iso messages and response to them but I do not know how can I use jPOS for this propose.
I searched for this in the internet but could not find any resource that answer we clearly. My main question is that whether I need to create an application using jPOS for implementing my requirements or only installing the jPOS on the server is enough for testing my client app?
Well, read jpos library documentation its draft version is available on the web you can find it here
Specific to your question about JPOS Server better to implement your own server. JPos provides class ISOServer e.g. following beans initiates a ISO Server in applicationContext.xml file
<bean id="paymentServer" class="org.jpos.iso.ISOServer">
<constructor-arg>
<value>13000</value>
</constructor-arg>
<constructor-arg ref="paymentChannel" />
<constructor-arg ref="paymentServerThreadPool" />
</bean>
<bean id="paymentChannel" class="org.jpos.iso.channel.ASCIIChannel">
<constructor-arg ref="paymentPackager" />
</bean>
<bean id="paymentPackager" class="com.sample.payment.packager.PaymentPackager"/>
<bean id="paymentServerThreadPool" class="org.jpos.util.ThreadPool">
<constructor-arg>
<value>1</value>
</constructor-arg>
<constructor-arg>
<value>100</value>
</constructor-arg>
<constructor-arg>
<value>PaymentServer</value>
</constructor-arg>
</bean>
<bean id="paymentProcessor" class="com.sample.processors.PaymentProcessor" init-method="init"/>
Following class to implement packager
public class PaymentPackager extends ISOBasePackager {
protected ISOFieldPackager fld[] = {
/* 0000 */ new IFB_NUMERIC ( 4, "Message Type Indicator", false),
/* 0001 */ new IFB_BITMAP ( 16, "Bitmap"),
/* 0002 */ new IFB_LLLCHAR (999, "Primary Account number"),
/* 0003 */ new IFB_NUMERIC ( 6, "Processing Code", true),
/* 0004 */ new IFB_NUMERIC ( 12, "Amount, Transaction", true),
//.....
/* 0063 */ new IFB_LLLCHAR (999, "Reserved for national use"),
/* 0064 */ new IFB_BINARY ( 20, "Message authentication code field"),
//.....
/* 0125 */ new IF_UNUSED (),
/* 0126 */ new IF_UNUSED (),
/* 0127 */ new IF_UNUSED (),
/* 0128 */ new IFB_BINARY ( 20, "Message authentication code field"),
};
public PaymentPackager() {
super();
setFieldPackager(fld);
}
}
In application entry point class you can get the bean and use like following to attach the channel listener
paymentServer.addISORequestListener(paymentProcessor);
following is the sample listener
public class PaymentProcessor implements ISORequestListener {
private static Logger log = LoggerFactory.getLogger(PaymentProcessor.class);
public void init() {
//do init
}
public boolean process (ISOSource source, ISOMsg m){
log.debug(">PaymentProcessor.process");
ISOMsg request = (ISOMsg) m.clone();
ISOMsg response = new ISOMsg();
//...
//build your response
//...
source.send(response);
return true;
}
}
NOTE: I have not implemented it yet but jpos provides new way to implement server and client using Q2 you can see documentation of QServer class to implement server, I'll try to share sample as soon as I could.
Happy coding :)
Related
My project needed SSL authentication mechanism to be EXTERNAL(using SSL certificates only and avoiding username/password on rabbitmq). For the connectionfactory bean we gave property name="saslConfig" value= "DefaultSaslConfig.EXTERNAL", but we are getting an error: "Cannot convert value of type [java.lang.String] to required type [com.rabbitmq.client.SaslConfig] for property 'saslConfig': no matching editors or conversion strategy found". we tried other values like value= "com.rabbitmq.client.DefaultSaslConfig.EXTERNAL" and value="EXTERNAL", but still the error persists. Can you please check on the configuration and logs below and provide me your suggestions.
Bean configuration
<rabbit:connection-factory id="connectionFactory" connection-factory="clientConnectionFactory" host="x.y.z.m" port="5671"/>
<bean id="clientConnectionFactory" class="org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean">
<property name="useSSL" value="true" />
<property name="saslConfig" value=com.rabbitmq.client.DefaultSaslConfig.EXTERNAL"/>
<property name="sslPropertiesLocation" value="classpath:/rabbitSSL.properties"/></bean>
Logs
Caused by: java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.rabbitmq.client.SaslConfig] for property 'saslConfig': no matching editors or conversion strategy found
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:306)
at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:576)
The following worked for me (source: https://github.com/spring-projects/spring-boot/issues/6719#issuecomment-259268574):
#PostConstruct
public void init() {
if (rabbitProperties.getSsl().isEnabled() && rabbitProperties.getSsl().getKeyStore() != null) {
cachingConnectionFactory.getRabbitConnectionFactory().setSaslConfig(DefaultSaslConfig.EXTERNAL);
}
}
EXTERNAL is a static variable, not an enum.
Use
"#{T(com.rabbitmq.client.DefaultSaslConfig).EXTERNAL}"
which is a SpEL expression using the type operator (T) to get a reference to the static.
See SpEL
We can use ConnectionFactoryCustomizer in package org.springframework.boot.autoconfigure.amqp
to set sasl config on rabbitmq connection factory on bean creation.
#Autowired
RabbitProperties rabbitProperties
#Bean
ConnectionFactoryCustomizer connectionFactoryCustomizer() {
if (rabbitProperties.getSsl().getEnabled() && rabbitProperties.getSsl().getKeyStore() != null) {
return (connectionFactory) -> connectionFactory.setSaslConfig(DefaultSaslConfig.EXTERNAL)
}
return (connectionFactory) -> connectionFactory.setSaslConfig(DefaultSaslConfig.PLAIN)
}
I'm using apache-cxf 2.7.11 + jackson (codehaus) 1.9.13 + spring 3.5 in my REST services web-container. I was wondering what would be the best way to remove null value fields from REST responses.
For example:
My response is now like this:
{
"name": "MyName",
"age": 10,
"address": null
}
I want my response to be like this (the address field has been removed):
{
"name": "MyName",
"age": 10
}
I've read about apache-cxf interceptors and filters here:
http://cxf.apache.org/docs/jax-rs-filters.html
http://cxf.apache.org/docs/jax-rs-data-bindings.html
and wondering what is the best practice? is there any configurable setting that I can change instead of implementing my own filer or interceptor class?
I'm using beans.xml file for configuration, thus I'm looking on how to config it all here, where my beans are:
<bean id="jaxrsRestJacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper"/>
<bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider">
<property name="mapper" ref="jaxrsRestJacksonObjectMapper"/>
</bean>
<jaxrs:server id="restContainer" address="/">
<jaxrs:serviceBeans>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
Cheers!
Found it!
This is the answer I was looking for:
see the updated beans.xml file:
<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper">
<property name="serializationInclusion" value="NON_NULL"/>
</bean>
<bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider">
<property name="mapper" ref="jacksonObjectMapper"/>
</bean>
You could add
#JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
on top of your POJO class. This would ignore the null fields for that one class.
Or you could configure the ObjectMapper so it would apply globally
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
If you go with the latter, you can pass the ObjectMapper as a constructor arg to the JacksonJsonProvider or JacksonJaxbJsonProvider (whichever one you are currently using)
UPDATE
You could also use a ContextResolver as seen here, and register the ContextResolver like you would any other provider. This will work better more complicated configurations. You might want to do that instead. With the ContextResolver, you don't need to configure the ObjectMapper with the JacksonJsonProvider, but you still do need the JacksonJsonProvider.
I use Spring security to authenticate users. If a user requests a secured page, he has to authenticate over a login page. If the user is always authenticated, he will be redirected to the requested page immediatly. Moreover some pages need special access rights, and so I setup an access-denied-page temporarily. So far so good.
The scenario:
The scenario definies, that the user will get a login-form instead of a static access-denied page, so that a different user can authenticate and if authentication is successful the requested page that needs the higher privileges will open.
The actual spring configuration reads:
<security:http auto-config="true" use-expressions="true" disable-url-rewriting="true">
<security:intercept-url pattern="/index.jsp" access="permitAll" />
<security:intercept-url pattern="/loginView" access="permitAll" />
<security:intercept-url pattern="/accessDenied" access="permitAll"/>
<security:intercept-url pattern="/user" access="hasRole('ROLE_USER')" />
<security:intercept-url pattern="/admin" access="hasRole('ROLE_ADMIN')" />
<security:intercept-url pattern="/**" access="denyAll"/>
<security:form-login login-page="/loginView"
authentication-failure-url="/loginView"
default-target-url="/dirView" />
<security:logout />
<security:access-denied-handler ref="accessDeniedHandler" />
</security:http>
The accessDeniedHandler-Bean:
public class AccessDeniedServletRequestHandler implements AccessDeniedHandler {
/** {#inheritDoc} */
#Override
public void handle(HttpServletRequest req, HttpServletResponse resp,
AccessDeniedException accessDeniedException) throws IOException,
ServletException {
RequestDispatcher d = req.getRequestDispatcher("/loginView");
d.forward(req, resp);
}
}
But that implementation of AccessDeniedHandler only forwards to the loginView. After authentication of an admin the default-success-page is openend and not the original requested page. I also tried to save the original request by calling HttpServletRequest#getAttribute("javax.servlet.forward.servlet_path"), but I don't understand how to force spring security to use that original request instead of the default target url.
Besides I read about org.springframework.security.web.savedrequest.SavedRequest that is used inside spring authentication to remember the original request if an unauthenticated user requests a page. But I don't find a valid way how to use the SavedRequest in the same manner for my access denied scenario.
Thanks in advance for suggestions and solutions.
I think your requirements should be satisfied by using the RequestCache API.
If you modify your http configuration you can use the request-cache namespace element:
<security:http>
...
<security:request-cache ref="requestCache"
</security:http>
<bean id="requestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache" />
You can also inject it into your AccessDeniedHandler. Then all you should need is a simple to saveRequest to setup the cached request which should be restored post-authentication:
public class AccessDeniedServletRequestHandler implements AccessDeniedHandler {
// Inject this into your class.
private RequestCache requestCache;
#Override
public void handle(HttpServletRequest req, HttpServletResponse resp,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
requestCache.saveRequest(req, resp);
RequestDispatcher d = req.getRequestDispatcher("/loginView");
d.forward(req, resp);
}
}
Strictly speaking, you don't actually need to do the bit with the namespace at all, since HttpSessionRequestCache is stateless (it's the internal implementation which is used if you don't override it in the namespace). So you could just create one directly in your AccessDeniedHandler class and it would still work.
I want to intercept a method call before execution using spring.NET. Let's assume the class/method to be intercepted is:
public class Listener
{
public void Handle()
{
// method body
}
}
This is what I've done (assuming all code is in a namespace called Example):
1.Created the advice:
public class MyAopAdvice : IMethodBeforeAdvice
{
public void Before(MethodInfo method, object[] args, object target)
{
// Advice action
}
}
2.Updated my spring xml configs:
<object id="myAopAdvice" type="Example.MyAopAdvice" />
<object id="listener" type="Spring.Aop.Framework.ProxyFactoryObject">
<property name="Target">
<object type="Example.Listener" autowire="autodetect"/>
</property>
<property name="InterceptorNames">
<list>
<value>myAopAdvice</value>
</list>
</property>
</object>
For some reason my Advice code is not getting hit if I put a breakpoint in it. However, if I add some console logging statements within my advice, it seems they are logged, but not at the appropriate time (i.e., before calling Listener.Handle()).
I'm willing to bet my configs are wrong (for once, I may be missing a way to tell the configs to listen for just the Handle method call and not any other method that Listener may have). Any ideas what's wrong?
Declare your Handle method as virtual:
public virtual void Handle() // ...
Your class does not implement any interfaces, which spring.net's default aop mechanism uses to create proxies. When spring.net does not find any interfaces to proxy, it looks for virtual methods to create a proxy for a class.
I'm using Apache-CXF for JAX-RS implementation. I have two resources which are defined in two bean. My jaxrs-server in context.xml os as follow
<jaxrs:server id="serverId" address="/">
<jaxrs:serviceBeans>
<bean id="bean1" class="com.Bean1" />
<bean id="bean2" class="com.Bean2" />
</jaxrs:serviceBeans>
</jaxrs:server>
Interface for Bean1 is as follows -
#Path("/")
public interface IBean1 {
#GET
#Path("/beaninfo1")
#Produces({ MediaType.APPLICATION_XML })
public Response checkBean1();
}
Interface for Bean2 is as follows -
#Path("/")
public interface IBean2 {
#GET
#Path("/beaninfo2")
#Produces({ MediaType.APPLICATION_XML })
public Response checkBean1();
}
I'm unable to hit the resource which is defined in last in serviceBans definition. In this case i'm able to hit Bean2 but not Bean1, getting 404 error, where as if i put Bean2 first and then Bean1, i'm able to hit Bean1 only.
Is there anything wrong with my configuration ?
It is possible to have the same #Path annotation at class level. You need to use a resourcecomparator. Please check this question
Yes. Give them different #Path annotations at the class level.