IllegalFlowLogicException: A FlowLogicRef cannot be constructed for FlowLogic - java

In my Corda I am trying to call a flow using RPC but I am getting this error while making the call to initiate the flow:
net.corda.core.flows.IllegalFlowLogicException: A FlowLogicRef cannot
be constructed for FlowLogic of type
com.example.flow.PolicyFlow$Initiator: due to missing constructor for
arguments: [class com.example.state.PolicyState]
My Flow is shown in the snippet below:
public SignedTransaction call() throws FlowException {
class SignTxFlow extends SignTransactionFlow {
private SignTxFlow(FlowSession otherPartyFlow, ProgressTracker progressTracker) {
super(otherPartyFlow, progressTracker);
}
#Override
protected void checkTransaction(SignedTransaction stx) {
requireThat(require -> {
ContractState output = stx.getTx().getOutputs().get(0).getData();
require.using("This must be an Policy transaction.", output instanceof PolicyState);
PolicyState policy = (PolicyState) output;
require.using("I won't accept Policy without a first Name.", (!(policy.getFirstName().equals(""))));
return null;
});
}
}
return subFlow(new SignTxFlow(otherPartyFlow, SignTransactionFlow.Companion.tracker()));
}
The Function for RPC Connection and initiating the flow is given below:
Can someone help me with this?

Please check the constructor of PolicyFlow$Initiator Class there is a mismatch in constructor: you are sending policy but the constructor expects something else as I can see in code you provided in comments. there is no constructor in that class that accepts a policy state. You've a constructor with 10 fields.

Related

Where to use #SuppressWarnings("requestfactory")

I'm trying to build a simple (read-only) web app with GWT and RequestFactory, and I can't work out how to get rid of following warning:
warning: The domain type DDisplay is not default-instantiable. Calling RequestContext.create(DDisplayProxy.class) will cause a server error.
Add #SuppressWarnings("requestfactory") to dismiss.
The problem being, I have pasted #SuppressWarnings("requestfactory") above every possibly relevant class, interface and method, but I still get this message.
As my requestfactory is read-only, I'm not going to call RequestContext.create, so this is not a concern. It would just be nice to get rid of the warning (without creating a DDisplay locator class).
On the server side I have a domain object DDisplay, and a DAO, DDisplayService.
public class DDisplay {
public String getTitle () {
return "title";
}
}
and
public class DDisplayService {
public DDisplay getDisplayByUUID (String uuid) {
return new DDisplay ();
}
}
I have the following for RequestFactory:
#ProxyForName("com.foobar.server.display.DDisplay")
public interface DDisplayProxy extends EntityProxy {
String getTitle ();
}
and
public interface DisplayRequestFactory extends RequestFactory {
#ServiceName(
value="com.foobar.server.display.DDisplayService"
,locator="com.foobar.server.display.SpringServiceLocator"
)
public interface DisplayRequestContext extends RequestContext {
Request <DDisplayProxy> getDisplayByUUID (String id);
}
DisplayRequestContext display ();
}
Can anyone tell me where to put the #SuppressWarnings("requestfactory") to get rid of this error please? Or is there another way of doing this - do I just need to add a never-used Locator class?
thanks,
Jim
From reading the source where the error message come from, it appears that you can add this to your EntityProxy, DDisplayProxy. Something like this:
#SuppressWarnings("requestfactory")
#ProxyForName("com.foobar.server.display.DDisplay")
public interface DDisplayProxy extends EntityProxy {
String getTitle();
}
This from reading the source of com.google.web.bindery.requestfactory.apt.DomainChecker#visitType, which if currentTypeIsProxy is true and there is no locator, and the type isn't instatiable, the warning is emitted. From inside of state.warn(...) (which is given the proxy type element), it checks for the presence of the #SuppressWarnings annotation on that type.

JPA.withTransaction executing other controllers method error: Global.java:39: error: 'void' type not allowed here

I am trying to execute some db insert/update queries in some time intervals.
To achive this I'decided to use Playframework built in Akka Actor system.
I have my class with method:
public class Global extends GlobalSettings {
#Override
public void onStart(Application application) {
Akka.system().scheduler().schedule(
Duration.create(1, TimeUnit.SECONDS), // start task delay
Duration.create(24, TimeUnit.HOURS), // between task instance delay
//Duration.create(24, TimeUnit.HOURS), // between task instance delay
new Runnable() {
#Override
public void run() {
JPA.withTransaction(
ImportCrmData.start()
);
}
},
Akka.system().dispatcher()
);
And the method that is called by the actor system:
public class ImportCrmData extends Controller {
#Transactional
public static void start() {
List<Customer> customersToUpdate = CustomerCRM.importCrmData();
for(Customer c: customersToUpdate) {
c.toDataBase();
}
}
}
I am getting an error on compile:
[error] app/modules/common/app/Global.java:39: error: 'void' type not allowed here ImportCrmData.start()
I understand that the problem occurs cause JPA.withTransaction() demand me to return from ImportCrmData.start() return Callback0 or Function0<>, but I dont know how to do it.
My method is just doing this.persist. Why should I even return something from that?
ImportCrmData is a controller thus it must return a valid http response (a result). A typical use case:
public class CustomerController extends Controller {
public static Result getCustomers() {
List<Customer> customers = CustomerService.getCustomers();
return ok(Json.toJson(customers));
}
}
Above example consists of controller which is an entry point to your application and reacts with client requests. CustomerService encapsulates logic related to getting customers. ok(...) returns an implementation of Result - a valid http response with code 200 and in above scenario, json body. It is implemented in Controller base class. Next your controller can be mapped in routes file to a url like so:
GET /customers controller.CustomerController.getCustomers
Applying above pattern you should have:
CrmController - entry point
CrmService - actual business logic
This separation allows using your CrmService in Global class, as well as in Controller layer without duplicating logic. Mind this is just a suggestion.

XML-RPC: how to make login credentials accessible to procedure calls?

Say my server exports the following procedure:
List listFiles(int userId);
I can't allow just any user to list files for a given user. They need to have authorization to do so.
My XML-RPC service uses basic auth to authenticate users.
What would be the recommended way to make the login credentials (the current user object) accessible to the procedure calls?
If you write your own XmlRpcServlet subclass (see http://ws.apache.org/xmlrpc/server.html section Basic Authentication for an example), you could stick the user credentials on a ThreadLocal (see http://java.dzone.com/articles/java-thread-local-%E2%80%93-how-use).
I discovered the solution. The key is to subclass the RequestProcessorFactoryFactory and specify to the Handler that you wish to use your subclass.
http://ws.apache.org/xmlrpc/apidocs/org/apache/xmlrpc/server/RequestProcessorFactoryFactory.RequestSpecificProcessorFactoryFactory.html
protected java.lang.Object getRequestProcessor(java.lang.Class pClass,
XmlRpcRequest pRequest)
throws XmlRpcException
Subclasses may override this method for request specific configuration. A typical subclass will look like this:
public class MyRequestProcessorFactoryFactory
extends RequestProcessorFactoryFactory.RequestSpecificProcessorFactoryFactory {
protected Object getRequestProcessor(Class pClass, XmlRpcRequest pRequest) {
Object result = super.getRequestProcessor(pClass, pRequest);
// Configure the object here
...
return result;
}
}
Parameters:
pRequest - The request object.
Throws:
XmlRpcException
Here's an example telling the default handler to use your Factory:
public class EchoServer {
public static void main(String[] args) throws Exception {
WebServer webServer = new WebServer(8080);
XmlRpcServer xmlRpcServer = webServer.getXmlRpcServer();
PropertyHandlerMapping phm = new PropertyHandlerMapping();
EchoService echo = new EchoServiceImpl();
phm.setRequestProcessorFactoryFactory(new MyRequestProcessorFactoryFactory());
phm.setVoidMethodEnabled(true);
phm.addHandler(EchoService.class.getName(), EchoService.class);
xmlRpcServer.setHandlerMapping(phm);
XmlRpcServerConfigImpl serverConfig = (XmlRpcServerConfigImpl) xmlRpcServer.getConfig();
serverConfig.setEnabledForExtensions(true);
serverConfig.setContentLengthOptional(false);
webServer.start();
}
}
So to answer my original question, I would create a RequestProcessorFactoryFactory as folows:
public class MyRequestProcessorFactoryFactory
extends RequestProcessorFactoryFactory.RequestSpecificProcessorFactoryFactory {
protected Object getRequestProcessor(Class pClass, XmlRpcRequest pRequest) {
Object result = super.getRequestProcessor(pClass, pRequest);
// Configure the object here
ClassOfObjectBeingExposedViaXmlRpc obj = (ClassOfObjectBeingExposedViaXmlRpc) result;
XmlRpcHttpRequestConfig httpRequest = (XmlRpcHttpRequestConfig) pRequest.getConfig();
MyUserClass user = authenticateSomehow(httpRequest.getBasicUserName(), httpRequest.getBasicPassword());
obj.setUser(user);
return result;
}
}
Thus the XML-RPC exposed object will be able to reference the authenticated user and authorize methods accordingly.

Can an object know from which object its method is called?

In Moritz Haarmann's Blog I found an example of usage of Bonjour by Java. Here is the code taken from there:
public class ServiceAnnouncer implements IServiceAnnouncer, RegisterListener {
private DNSSDRegistration serviceRecord;
private boolean registered;
public boolean isRegistered(){
return registered;
}
public void registerService() {
try {
serviceRecord = DNSSD.register(0,0,null,"_killerapp._tcp", null,null,1234,null,this);
} catch (DNSSDException e) {
// error handling here
}
}
public void unregisterService(){
serviceRecord.stop();
registered = false;
}
public void serviceRegistered(DNSSDRegistration registration, int flags,String serviceName, String regType, String domain){
registered = true;
}
public void operationFailed(DNSSDService registration, int error){
// do error handling here if you want to.
}
}
I have a question about the "serviceRegistered" method. As far as I understand it is called during (or after) registration of the service (and it sets variable "registered" to be equal to "true"). But what is not clear to me is how exactly it is called. Because the service is registered by the method "registerService". This method, in its turn, calls "DNSSD.register". And, as far as I understand, the "DNSSD.register" will call the "serviceRegister" method of the "ServiceAnnouncer" class. But how "DNSSD.register" knows that it needs to call a method of the "ServiceAnnouncer" class? Can "DNSSD.register" know that it is called from a particular class (in this case "ServiceAnnouncer" class)?
The ServiceAnnouncer has passed itself as last argument of the DNSSD.register() method, which in turn is apparently expecting any instance of RegisterListener. This way the DNSSD can have a direct handle to the ServiceAnnouncer instance.
It seems that this class is a listener - namely RegisterListener. It has been registered as a listener in DNSSD by passing itself to the register(..) method.
For more information read about the Observer pattern.

Mocking inside a Java class

So I have this GWT code that handles RPC requests maintain states(ready, waiting, error etc).
And I would like to check if the class change its states correctly after each call, set response variables etc.
Now how should I proceed to test that without making actual requests to the server(that could run into errors in the server it self).
I think I could mock the request callback class somehow but it is invisible to the test.
I'm lost, help!
Sample of the code below(I'll post the whole thing later in case anyone wants).
public class RPCHandler
{
public RPCHandler(String method,String[] argumentsName,
String[][] argumentsValues)
{
this.method = method;
this.argumentsName = argumentsName;
this.argumentsValues = argumentsValues;
}
/**
* Method that creates a RPC request using JSON in a POST
*
*/
public void rpcRequest(){
if(currentState == HandlerState.WAITING_RESPONSE)return;
currentState = HandlerState.WAITING_RESPONSE;
// Append watch list stock symbols to query URL.
url = URL.encode(url);
url += "action=";
url += method;
// Send request to server and catch any errors.
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, url);
String requestData = parseToJSON(argumentsName, argumentsValues);
try{
Request request = builder.sendRequest(requestData, new RequestCallback()
{
public void onError(Request request, Throwable exception)
{
setRPCException(new Exception("Error while saving. Action="+method));
setCurrentState(HandlerState.ON_ERROR);
}
//Few other error, response received hander methods after this point.
}
}
It looks like you're trying to mock out the actual transport so you should build a mock of the RequestBuilder class. In JMockit, you could write:
public class MockRequestBuilder
{
public void $init( int method, String url)
{
/* check values and/or store for later */
}
public Request sendRequest( String data, RequestCallback callback )
{
/* check values and/or store for later */
}
}
You'll need to fill in the details of the what you want the mock to do. Also, you can isolate the callback testing if you moved the callback to a named class instance inside of your outer class:
public class MyGWTClass
{
protected static class RpcCallback extends RequestCallback
{
public void onError(...) { ... }
}
}
By moving the callback object into a class and using a factory method, you can create tests that only check the callback.

Categories