CordaApp with Spring Boot Api different response - corda

I have integrated the cordapp with spring boot .One strange observation we found that the response differs coming from the cordawebserver and spring boot server for example
Blockquote
API :GET: market/me
gives
{
“me”: {
“commonName”: null,
“organisationUnit”: null,
“organisation”: “PartyG-CT”,
“locality”: “Tokyo”,
“state”: null,
“country”: “JP”,
“x500Principal”: {
“name”: “O=PartyG-CT,L=Tokyo,C=JP”,
“encoded”: “MDExCzAJBgNVBAYTAkpQMQ4wDAYDVQQHDAVUb2t5bzESMBAGA1UECgwJUGFydHlHLUNU”
}
}
}
with Spring boot
while with cordawebserver we are getting :
{
“me”: “C=JP,L=Tokyo,O=PartyG-CT”
}
Same behaviour we are finding the same for different APIs Any help will be appreciated
#GET
#Path("peers")
#Produces(javax.ws.rs.core.MediaType.APPLICATION_JSON)
// CordaX500Name
public Map<String, List<CordaX500Name>> getPeers() {
List<NodeInfo> nodeInfoSnapshot = proxy.networkMapSnapshot();
return ImmutableMap.of(
"peers",
nodeInfoSnapshot
.stream()
.map(node -> node.getLegalIdentities().get(0).getName())
.filter(name -> !name.equals(myLegalName) && !name.getOrganisation().equals(controllerName)
&& !name.getOrganisation().equals(NETWORK_MAP_NAME))
.collect(toList()));
}
//boot entry point
#SpringBootApplication
public class FacilityServer {
#Autowired
public static NodeRPCConnection nodeRPCConnection;
/**
* Starts our Spring Boot application.
*/
public static void main(String[] args) throws Exception {
SpringApplication springApplication = new SpringApplication();
springApplication.setBannerMode(Banner.Mode.OFF);
springApplication.run(FacilityServer.class, args);
}
#EventListener(ApplicationReadyEvent.class)
public void initiateFacilityObserverPostStartup() throws Exception{
FacilityObserver.startFacilityWatch();
}
// this class for using the jersey instead of spring rest impltn
#Configuration
#ApplicationPath("rest")
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
}
#PostConstruct
public void setUp() {
register(MarketApi.class);
//register(GenericExceptionMapper.class);
}
}

I found the solution ;According to the corda documentation we need to register cordajackson mapper .Then, we will be able to get the same response as in corda webserer.
for example:
List<StateAndRef<YourState>> vaultStatesList = vaultStates.getStates();
ObjectMapper mapper = JacksonSupport.createNonRpcMapper();
String json = mapper.writeValueAsString(vaultStatesList);

Related

Spring redis unable to autowire repository

I'm using custom crudrespository to persist data in redis. However, I'm unable to autowire custom repository.
All the configuration seems correct and redis is running on my local.
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface CustomRepository extends CrudRepository<String,
Long> {
String get(String key);
void put(String key, String value);
}
//////////
public class StorageServiceImpl implements IStorageService {
#Autowired
private CustomRepository respository;
#Override
public void saveParameter() {
this.respository.put("key1","value1");
}
#Override
public String getParameter() {
return this.respository.get("key1");
}
/////
#Service
public interface IStorageService {
void saveParameter();
String getParameter();
}
///////
#SpringBootApplication(scanBasePackages = {"com.example.cache"})
#EnableRedisRepositories(basePackages = {"com.example.cache.repository"})
public class ApplicationConfiguration {
public static void main(String[] args){
SpringApplication.run(ApplicationConfiguration.class, args);
new StorageServiceImpl().saveParameter();
System.out.println(new StorageServiceImpl().getParameter());
}
}
When I try running this application using gradle bootRun, I get
Exception in thread "main" java.lang.NullPointerException
at com.example.cache.impl.StorageServiceImpl.saveParameter(StorageServiceImpl.java:16)
at com.example.cache.ApplicationConfiguration.main(ApplicationConfiguration.java:17)
Not sure what's wrong?
You can't use new on any bean, you need to #Autowire it. The annotations only work with spring managed beans at every level.
Add a new bean with a a storage service and a method that makes your call after it is created.
Also, I can't remember if the spring-boot creates the bean if there is only one implementation but I believe your StorageServiceImpl needs the #Service annotation, not the interface.
Delete this from your ApplicationConfiguration class.
new StorageServiceImpl().saveParameter();
System.out.println(new StorageServiceImpl().getParameter());
Then add this new class.
#Service
public class Startup {
#Autowired
IStorageService storageService;
#PostConstruct
public void init(){
storageService.saveParameter();
System.out.println(storageService().getParameter());
}
}
And you need a config
#Configuration
#EnableRedisRepositories
public class ApplicationConfig {
#Bean
public RedisConnectionFactory connectionFactory() {
return new JedisConnectionFactory();
}
#Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
return template;
}
}

Spring boot 1.4 Integration tests pass but Application start fails

We just upgraded to Spring Boot 1.4 and are using the Spring Boot testing improvements. We have integration tests of the form:
RunWith(SpringRunner.class)
#SpringBootTest(classes = {
ApplicationConfiguration.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ServiceIntegrationTest {
private static final String AEndpoint = Constants.A_REST_CONTROLLER_ENDPOINT;
private static final String TEndpoint = Constants.T_REST_CONTROLLER_ENDPOINT;
#Autowired
private TestRestTemplate testRestTemplate;
public void postJsonNode(String postUrl, JsonNode requestBody) {
HttpEntity<JsonNode> request = new HttpEntity<JsonNode>(requestBody, this.headers);
ResponseEntity<String> post = this.testRestTemplate.postForEntity(postUrl, request, String.class);
assertThat(post.getStatusCode(), equalTo(HttpStatus.CREATED));
}
These kinds of tests pass but the Application fails to start due to ObjectMapper getting deprecated and replaced by a pre-wired _halMapper (I referred to as bean wiring issue).
***************************
APPLICATION FAILED TO START
***************************
Description:
Constructor in org.springframework.boot.actuate.autoconfigure.EndpointMBeanExportAutoConfiguration required a single bean, but 2 were found:
- objectMapper: defined by method 'objectMapper' in com.service.ApplicationConfiguration
- _halObjectMapper: defined in null
Application class:
public class Application {
public static void main(String[] args) {
SpringApplication.run(ApplicationConfiguration.class, args);
}
}
ApplicationConfiguration class:
#SpringBootApplication(scanBasePackages = "com.service")
public class ApplicationConfiguration {
#Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
return objectMapper;
}
}
Is there a way to test the Application start through integration tests?

How to write a mockito test case for ResourceAssembler with in Spring Hateos?

I am trying to write a unit test for the below Assembler but i keep getting Could not find current request via RequestContextHolder. Is this being called from a Spring MVC handler?. I wanted to know how i can mock out the resource creation?
#Component
public class LoginResourceAssembler extends ResourceAssemblerSupport<User, ResourceSupport> {
public LoginResourceAssembler() {
super(User.class, ResourceSupport.class);
}
#Override
public ResourceSupport toResource(User user) {
ResourceSupport resource = new ResourceSupport();
final String id = user.getId();
resource.add(linkTo(MyAccountsController.class).slash(id).slash("accounts").withRel("accounts"));
return resource;
}
}
Instead of changing from a plain unit test to a IMO integration test (given dependency of the spring framework) you could do something like:
#RunWith(MockitoJUnitRunner.class)
public class LoginResourceAssemblerTest {
#InjectMocks
private LoginResourceAssembler loginResourceAssembler;
#Before
public void setup() {
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(new MockHttpServletRequest()));
}
#Test
public void testToResource() {
//...
}
}
I was seeing the error Could not find current request via RequestContextHolder. Is this being called from a Spring MVC handler because my test class was annotated with #RunWith(MockitoJUnitRunner.class) and this was not injecting the controller.
To fix this error, i annotated my test case with
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
A working test case in my case
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
public class LoginResourceAssemblerTest {
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
#InjectMocks
private LoginResourceAssembler loginResourceAssembler;
#Before
public void setUp() {
initMocks(this);
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
#Test
public void testToResource() {
User user = new User();
user.setId("1234");
ResourceSupport resource = loginResourceAssembler.toResource(user);
assertEquals(1,resource.getLinks().size());
assertEquals("accounts",resource.getLinks().get(0).getRel());
assertTrue(resource.getLinks().get(0).getHref().contains("accounts"));
}
}

Apache Camel Integration test results in OutOfMemory

I have a simple Camel route that sends data to an external REST interface, integrated with Spring MVC.
#RestController
public class MyController {
#Autowired
private camelService camelService;
#RequestMapping(method = RequestMethod.POST, value = "/test")
#ResponseStatus(HttpStatus.CREATED)
public TestModel createEV(#Valid #RequestBody TestModel testModel) {
camelService.publishTestCase(testModel);
return testModel;
}
}
#Service
public class CamelService {
#Produce(uri = "direct:test")
private ProducerTemplate producerTemplate;
#Override
public void publishTestCase(TestModel testModel) {
producerTemplate.sendBody(testModel);
}
}
#Component
public class TestRouter extends SpringRouteBuilder
#Override
public void configure() throws Exception {
errorHandler(loggingErrorHandler(log).level(LoggingLevel.ERROR));
from("direct:test")
.routeId("testRoute")
.beanRef("mapper", "map")
.to("velocity:test.vm")
.setHeader(Exchange.HTTP_METHOD, simple("POST"))
.to("log:test?level=DEBUG&showAll=true&multiline=true&maxChars=100000")
.to("cxfrs:http://url.here");
}
}
Then there's an integration test for the rest endpoint with mockMvc that mocks the external camel endpoint.
#ContextConfiguration(loader = SpringApplicationContextLoader, classes = Application)
#WebIntegrationTest
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
class MyControllerIntegrationTest extends Specification {
#Autowired
private CamelContext camelContext
MockMvc mockMvc
#Autowired
WebApplicationContext wac
#Shared
def setupOnceRun = false
#Shared
def validInput = new File(JSON_DIR + '/valid.json').text
def setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build()
// no way to use setupSpec as Autowired fields can't be Shared
if (!setupOnceRun) {
ModelCamelContext mcc = camelContext.adapt(ModelCamelContext);
camelContext.getRouteDefinition("testRoute).adviceWith(mcc, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
mockEndpointsAndSkip("cxfrs:http://url.here")
}
});
setupOnceRun = true
}
}
def 'valid scenario'() {
setup:
MockEndpoint mockEndpoint = (MockEndpoint) camelContext.hasEndpoint("mock:cxfrs:http://url.here")
mockEndpoint.expectedMessageCount(1)
when:
def response = mockMvc.perform(post('/test').content(validInput)).andReturn()
then:
response.getResponse().getStatus() == 201
mockEndpoint.assertIsSatisfied()
}
}
The test is passing if you run it by itself but once it's included in the build together with other integration tests it's constantly producing OutOfMemory. MaxPermSize is 4G, it doesn't look like that's an issue. I am new to Camel so my guess is that I am wiring the test in a wrong way. Would appreciate any suggestions.

Spring MVC - How to create a proper Service layer?

I'm using SpringBoot and I am trying to create a service layer for my web application but i cant make it work.
My classes look like this
ServiceFactory
#Service
public class ServiceFactory {
#Autowired
public static EncuestaService getEncuestaService()
{
return new EncuestaServiceImpl();
}
}
EncuestaService
public interface EncuestaService {
void crearEncuesta(Encuesta encuesta, Map<String,String> parametros);
}
EncuestaServiceImpl
#Service
public class EncuestaServiceImpl implements EncuestaService {
#Override
public void crearEncuesta(Encuesta encuesta, Map<String, String> parametros) {
CrearEncuesta nueva = new CrearEncuesta(encuesta,parametros);
nueva.execute();
}
}
CrearEncuesta
#Service
public class CrearEncuesta {
private Encuesta encuesta;
private Map<String,String> parametros;
#Autowired
private RespuestasRepository respuestasRepository;
#Autowired
private EncuestasRepository encuestasRepository;
public CrearEncuesta(Encuesta encuesta, Map<String,String> parametros) {
super();
this.encuesta = encuesta;
this.parametros = parametros;
}
public void execute()
{
encuestasRepository.save(encuesta);
}
}
Everytime I call ServiceFactory.getEncuestasService().crearEncuesta() from any Controller it returns me a NullPointerException.
From what I have been reading I should not be creating a new EncuestsaServiceImpl() in my ServiceFactory but I don't really know the correct way to do so. I would appreciate if anyone could help me out :P.
Edit:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
Controller
#Controller
public class EncuestaController {
#RequestMapping(value ="registrarEncuesta", method = RequestMethod.POST)
private String formularioEncuesta(#Valid #ModelAttribute("formEncuesta") EncuestaForm formEncuesta, BindingResult bindingResult,#RequestParam Map<String,String> allRequestParams)
{
if (bindingResult.hasErrors()) {
return "nuevaEncuesta";
}
try {
Encuesta nueva = formEncuesta.toEncuesta();
ServiceFactory.getEncuestaService().crearEncuesta(nueva,allRequestParams);
} catch (DataIntegrityViolationException e) {
return "nuevaEncuesta";
}
return "redirect:/encuestas";
}
}
You will have to read a little bit more about dependency injection. The central principle in Spring Framework is dependency injection which should be used to avoid referencing beans (service implementations, repository implementations etc...) statically. Spring container also servers as a bean factory that will instantiate and inject (autowire) implementations to beans that need them.
Because Spring will instantiate service interface implementations for you, you don't need ServiceFactory. In your controller you need to add a reference (a field) to EncuestaService and annotate it as Autowired and Spring will wire in the implementation. And then you can just use it in your controller.
#Controller
public class EncuestaController {
#Autowired
EncuestaService encuestaService;
#RequestMapping(value ="registrarEncuesta", method = RequestMethod.POST)
private String formularioEncuesta(#Valid #ModelAttribute("formEncuesta") EncuestaForm formEncuesta, BindingResult bindingResult,#RequestParam Map<String,String> allRequestParams)
{
if (bindingResult.hasErrors()) {
return "nuevaEncuesta";
}
try {
Encuesta nueva = formEncuesta.toEncuesta();
encuestaService.crearEncuesta(nueva,allRequestParams);
} catch (DataIntegrityViolationException e) {
return "nuevaEncuesta";
}
return "redirect:/encuestas";
}
}

Resources