How to connect EJB, REST and Client? - java

I have 2 java projects in netbeans and I want to connect them. First is based on Jboss server and contains ejb and rest. EJB connects with databse and rest service packs object to xml and sends to client witch is standard swing based gui application. Problem is that I don't know what to do next, because I got null pointer exception when I try to recive any data from server. Am I doing it right way? Maybe my whole idea is wrong? Please help.
EDIT:
I figured that the fault is on server side. I don't know how to create a rest service. In class WholesaleREST in netbeans there were warning that rest is not configured. I clicked "Configure REST with Java EE6 Specification" and server can't deploy it and throws an error:
Deployment "vfs:///E:/Instalki/jboss/jboss-as-distribution-6.1.0.Final/jboss-6.1.0.Final/server/default/deploy/WholesaleApp.war" is in error due to the following reason(s): org.jboss.deployers.spi.DeploymentException: URL file:/E:/Instalki/jboss/jboss-as-distribution-6.1.0.Final/jboss-6.1.0.Final/server/default/tmp/vfs/automount6dbf7312f2f10b36/WholesaleApp.war-1ad4d6611c73bd02/ deployment failed
This error doesn't tell me anything about it and I dont know what to do. Any Ideas please?
End of added text, rest below is old.
Here is code I wrote:
EJB class:
#Stateless
public class WholesaleEJB {
#PersistenceContext(name="WholesaleAppPU")
EntityManager entityManager;
public List<Clients> getClients() {
Query q = entityManager.createQuery("select c from Clients c");
#SuppressWarnings("unchecked")
List<Clients> lista = q.getResultList();
return lista;
}
}
Rest class:
#Path("/wholesale")
#Stateless
public class WholesaleREST implements WholesaleInterface{
#EJB
WholesaleEJB bean;
#Override
#GET
#Path("/get")
public String getCars() {
List<Clients> listOfClients = bean.getClients();
StringWriter sw = new StringWriter();
ClientsContainer container = new ClientsContainer(listOfClients);
JAXB.marshal(container, sw);
return sw.toString();
}
}
Client side class with get method
public class HttpConnector {
public static String doGet(String url) {
try {
URLConnection connection = new URL(url).openConnection();
String charset = "UTF-8";
connection.setRequestProperty("Accept-Charset", charset);
return getResponse(connection);
} catch (Exception ex) {
ex.getMessage();
}
return null;
}
private static String getResponse(URLConnection connection)
throws UnsupportedEncodingException, IOException {
InputStream response = connection.getInputStream();
final char[] buffer = new char[0x10000];
StringBuilder out = new StringBuilder();
Reader in = new InputStreamReader(response, "UTF-8");
int read;
do {
read = in.read(buffer, 0, buffer.length);
if (read>0) {
out.append(buffer, 0, read);
}
} while (read>=0);
return out.toString();
}
}
And last class which access ejb methods from client side:
public class ClientRemoteAccess implements ClientInterface{
String url = "http://localhost:8080/WholesaleApp/wholesale";
#Override
public List<Clients> getClients() {
String recivedXML = HttpConnector.doGet(url+"/get");
ClientsContainer container = JAXB.unmarshal(
new StringReader(recivedXML), ClientsContainer.class);
return container.getListOfClients();
}
}

I think the architecture you want to achieve is something like this:
common-model: here you place the domain model, for example the JPA entities and the class ClientsContainer
restfull-service: depends on the common-model and contains the EJB/JPA layer that communicates with the database and the RESTful web service that exposes the data as resources.
restful-client: the swing rich client that depends on the common-model and communicates with the restfull-service via HTTP.
Note that there is no direct communication between the EJB and the client.

Related

Java Opensaml 3.4.6 : authnrequest subject is null - impossible to get user name

Developing a Java EE/JSF application, I am trying to include SAML sso functionality into it. Due to technical requirements (SAP BOBJ SDK) I need to use java 8, so I must stick with opensaml 3.x branch. As the application is some years old, I cannot add spring/spring-security to it just for SAML, that's why my code focuses on raw opensaml usage.
Mimicking the example code of this repository, I implemented the authentication basics:
This first code is called when I reach the "login" page. And send the AuthnRequest to my IDP
#Log4j2
#Named
public class SAMLAuthForWPBean implements Serializable {
private static final BasicParserPool PARSER_POOL = new BasicParserPool();
static {
PARSER_POOL.setMaxPoolSize(100);
PARSER_POOL.setCoalescing(true);
PARSER_POOL.setIgnoreComments(true);
PARSER_POOL.setIgnoreElementContentWhitespace(true);
PARSER_POOL.setNamespaceAware(true);
PARSER_POOL.setExpandEntityReferences(false);
PARSER_POOL.setXincludeAware(false);
final Map<String, Boolean> features = new HashMap<>();
features.put("http://xml.org/sax/features/external-general-entities", Boolean.FALSE);
features.put("http://xml.org/sax/features/external-parameter-entities", Boolean.FALSE);
features.put("http://apache.org/xml/features/disallow-doctype-decl", Boolean.TRUE);
features.put("http://apache.org/xml/features/validation/schema/normalized-value", Boolean.FALSE);
features.put("http://javax.xml.XMLConstants/feature/secure-processing", Boolean.TRUE);
PARSER_POOL.setBuilderFeatures(features);
PARSER_POOL.setBuilderAttributes(new HashMap<>());
}
private String idpEndpoint = "url de azure por";
private String entityId = "glados";
private boolean isLogged;
#Inject
private LoginBean loginBean;
#Inject
private MainBean mainBean;
#Inject
private TechnicalConfigurationBean technicalConfigurationBean;
#PostConstruct
public void init() {
if (!PARSER_POOL.isInitialized()) {
try {
PARSER_POOL.initialize();
} catch (ComponentInitializationException e) {
LOGGER.error("Could not initialize parser pool", e);
}
}
XMLObjectProviderRegistry registry = new XMLObjectProviderRegistry();
ConfigurationService.register(XMLObjectProviderRegistry.class, registry);
registry.setParserPool(PARSER_POOL);
// forge auth endpoint
}
public boolean needLogon() {
return isLogged;
}
public void createRedirection(HttpServletRequest request, HttpServletResponse response)
throws MessageEncodingException,
ComponentInitializationException, ResolverException {
// see this link to build authnrequest with metadata https://blog.samlsecurity.com/2011/01/redirect-with-authnrequest-opensaml2.html
init();
AuthnRequest authnRequest;
authnRequest = OpenSAMLUtils.buildSAMLObject(AuthnRequest.class);
authnRequest.setIssueInstant(DateTime.now());
FilesystemMetadataResolver metadataResolver = new FilesystemMetadataResolver(new File("wp.metadata.xml"));
metadataResolver.setParserPool(PARSER_POOL);
metadataResolver.setRequireValidMetadata(true);
metadataResolver.setId(metadataResolver.getClass().getCanonicalName());
metadataResolver.initialize();
/*
* EntityDescriptor urlDescriptor = metadataResolver.resolveSingle( new CriteriaSet( new BindingCriterion(
* Arrays.asList("urn:oasis:names:tc:SAML:2.0:bindings:metadata"))));
*/
/*entityId = "https://192.168.50.102:8443/360.suite/loginSAML.xhtml";*/
entityId = "glados";
//idp endpoint, je pense => à obtenir des metadata
authnRequest.setDestination(idpEndpoint);
authnRequest.setProtocolBinding(SAMLConstants.SAML2_POST_BINDING_URI);
// app endpoint
authnRequest.setAssertionConsumerServiceURL("https://192.168.1.14:8443/360.suite/loginSAML.xhtml");
authnRequest.setID(OpenSAMLUtils.generateSecureRandomId());
authnRequest.setIssuer(buildIssuer());
authnRequest.setNameIDPolicy(buildNameIdPolicy());
MessageContext context = new MessageContext();
context.setMessage(authnRequest);
SAMLPeerEntityContext peerEntityContext = context.getSubcontext(SAMLPeerEntityContext.class, true);
SAMLEndpointContext endpointContext = peerEntityContext.getSubcontext(SAMLEndpointContext.class, true);
endpointContext.setEndpoint(URLToEndpoint("https://192.168.1.14:8443/360.suite/loginSAML.xhtml"));
VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.setProperty("resource.loader", "classpath");
velocityEngine.setProperty("classpath.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
velocityEngine.init();
HTTPPostEncoder encoder = new HTTPPostEncoder();
encoder.setVelocityEngine(velocityEngine);
encoder.setMessageContext(context);
encoder.setHttpServletResponse(response);
encoder.initialize();
encoder.encode();
}
public String doSAMLLogon(HttpServletRequest request, HttpServletResponse response) {
isLogged = true;
technicalConfigurationBean.init();
return loginBean.generateSSOSession(request, technicalConfigurationBean.getSsoPreferences(),
new SamlSSO(technicalConfigurationBean.getCmsPreferences().getCms()));
}
private NameIDPolicy buildNameIdPolicy() {
NameIDPolicy nameIDPolicy = OpenSAMLUtils.buildSAMLObject(NameIDPolicy.class);
nameIDPolicy.setAllowCreate(true);
nameIDPolicy.setFormat(NameIDType.TRANSIENT);
return nameIDPolicy;
}
private Endpoint URLToEndpoint(String URL) {
SingleSignOnService endpoint = OpenSAMLUtils.buildSAMLObject(SingleSignOnService.class);
endpoint.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
endpoint.setLocation(URL);
return endpoint;
}
private Issuer buildIssuer() {
Issuer issuer = OpenSAMLUtils.buildSAMLObject(Issuer.class);
issuer.setValue(entityId);
return issuer;
}
}
The redirect is successfully processed and the IDP sends back a POST request to my application that call this code :
#Override
public IEnterpriseSession logon(HttpServletRequest request) throws SDKException, Three60Exception {
HTTPPostDecoder decoder = new HTTPPostDecoder();
decoder.setHttpServletRequest(request);
AuthnRequest authnRequest;
try {
decoder.initialize();
decoder.decode();
MessageContext messageContext = decoder.getMessageContext();
authnRequest = (AuthnRequest) messageContext.getMessage();
OpenSAMLUtils.logSAMLObject(authnRequest);
// Here I Need the user
String user = authnRequest.getSubject().getNameID().getValue();
// BOBJ SDK
String secret = TrustedSso.getSecret();
ISessionMgr sm = CrystalEnterprise.getSessionMgr();
final ITrustedPrincipal trustedPrincipal = sm.createTrustedPrincipal(user, cms, secret);
return sm.logon(trustedPrincipal);
} catch (ComponentInitializationException | MessageDecodingException e) {
return null;
}
}
The issue here is that getSubject() is null on this query.
What did I miss here? Do I need to perform other requests? Do I need to add other configuration in my AuthnRequest?
As stated in the comment, I found the reason why my code was not working.
As I also asked this question on a french forum, can can find the translation of this answer here.
Short answer :
Opensaml knows where to send the authn request thanks to the SAMLPeerEntityContext. In my code I put my own application as the target of this request instead of using the idp HTTP-POST bind endpoint. Once this was changed, everything worked, the idp was answering back the SAMLResponse with proper name.
Long version
On my code, I was building the entity context like this :
SAMLPeerEntityContext peerEntityContext = context.getSubcontext(SAMLPeerEntityContext.class, true);
SAMLEndpointContext endpointContext = peerEntityContext.getSubcontext(SAMLEndpointContext.class, true);
endpointContext.setEndpoint(URLToEndpoint("https://192.168.1.14:8443/360.suite/loginSAML.xhtml"));
This code forces the authn request to be sent to my own application instead of the IDP. As this is the request, it cannot contain the identity.
If I replace this URL by idpEndpoint which I got from the IDP metadata file, the full workflow works as expected.
First something will not work as my IDP forces requests to be signed, so I need to add a signature part.
The "signing and verification" sample of this repository just works for that.
Then, as I need a real identity, I must NOT ask for a transient nameid. In my tests, UNSPECIFIED worked, but PERSISTENT should also make it.
Last, in the ACS receiver, I do NOT receive an authn request but a SAMLResponse with assertions. The code will therefore look like :
String userName =
((ResponseImpl) messageContext.getMessage()).getAssertions().get(0).getSubject().getNameID()
.getValue();
I simplified the code but one, of course, has to check that :
(((ResponseImpl)messageContext.getMessage()).getStatus() is SUCCESS
signatures are valid
assertions are properly populated
Thanks #identigral for your answer in the comment

How to implement own factory in Spring

I have three or more types of request that come in form of JSON data and convert to object.
Let's say that there is a request:
{
"id":1,
"type":"0",
"url":
"http://stackoverflow.com"
}
And I want to build some sort of conncetion factory that allows me to get pages like that:
Request request = new Request(json);
Response response = request.execute();
Of course the execute method has different implementation for each of the request's types.
I have a prototype that is written in plain JavaSE and I want to migrate to Spring Framework and also get some feedback about my code if it has problems. First of all I built a SimpleRequest that just obtains the page and returns the body.
class SimpleRequest implements Request{
Package requestData;
#Override
public Connection.Response execute() throws IOException {
Connection.Response response = Jsoup
.connect(requestData.getUrl())
.execute();
return response;
}
public void bind(Package requestData){
this.requestData = requestData;
}
}
This method just fetch the page. Nothing interesting.
Also I have RequestTemplate that prepare request:
class RequestTemplate{
Package requestData;
RequestFactory requestFactory = new RequestFactory();
Request request;
public RequestTemplate(Package requestData){
this.requestData = requestData;
try {
request = requestFactory.getRequestInstance(requestData.getType());
request.bind(requestData);
}catch (Exception e){
e.printStackTrace();
}
}
public Connection.Response execute(){
Connection.Response connection = null;
try{
connection = request.execute();
}catch (Exception e){
e.printStackTrace();
}
return connection;
}
}
This method obtains an object based of RequestType;
And of course I have RequestFactory that has a description of objects and create new Instances of them.
class RequestFactory{
public Request getRequestInstance(RequestType type) throws Exception {
switch (type){
case SIMPLE:
return new SimpleRequest();
default:
throw new Exception("Error");
}
}}
So we check the RequestType type matching with the enum list and return new instance.
I also what to implement something like that in my small project that are based on Spring Framework and there are two issues.
As I understand the code above is a bit messy and has some performance problems. I think that I'll use the code to serve lots of connection so that I have to optimize it somehow because of memory limit and so on.
Integration with Spring. It's a framework so I think there should be some features that could make my life easier. I've read about FactoryBean, but haven't caught how to wire it with my task. As I mentioned above that the code is a bit messy and i think that i created to much abstraction.
Thanks.

How to send json data from android app and receive it in rest web service running in jersey?

I have made my rest web service code to start sever like this :
static final String BASE_URI = "http://10.236.51.14:9000/abcd/";
public static void main(String[] args) {
try {
HttpServer server = HttpServerFactory.create(BASE_URI);
server.start();
System.out.println("Press Enter to stop the server. ");
System.in.read();
server.stop(0);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
And in the rest web service I have made a basic code to receive 2 arguments and show their sum like this :
#GET
#Path("/add/{a}/{b}")
#Produces(MediaType.TEXT_XML)
public String add(#PathParam("a") double a, #PathParam("b") double b) {
return "<?xml version=\"1.0\"?>" + "<result>" + (a + b) + "</result>";
}
I want to send Json data (image) from my android app to this webservice but I don't know how to receive it in webservice and display it.
Here is the code from my android app. In this I have converted a bitmap to string using Base64. How should I send it to my webservice?
ByteArrayOutputStream baos = new ByteArrayOutputStream();
mybitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
String strBitMap = Base64.encodeToString(b, Base64.DEFAULT);
Any help will be appreciated :)
I have searched a lot but cant find appropriate code for my webservice to receive and display the json data. I am also struggling in sending this base64 string to the webservice in form of json.
Please help me out.
Best regards :)
I have a question: Does your example WebService work? I mean the one with the two arguments. If you call http://10.236.51.14:9000/abcd/add/1/2 in your browser does it display 3 correctly? If not you should have an ApplicationConfig containing your REST-interfaces. Those should be added as resource classes for example like this:
#ApplicationPath("api")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new HashSet<>();
resources.addAll(addServiceClasses());
resources.addAll(addFilterClasses());
return resources;
}
private Set<Class<?>> addServiceClasses() {
// add all your REST-classes here
Set<Class<?>> resources = new HashSet<>();
resources.add(YourCalculatorRestServiceClass.class);
resources.add(YourImageConsumingRestServiceClass.class);
return resources;
}
private Set<Class<?>> addFilterClasses() {
// add all your filter classes here (if you have any)
Set<Class<?>> resources = new HashSet<>();
resources.add(YourAuthenticationFilterClass.class);
resources.add(OtherFilterClass.class);
return resources;
}
#Override
public Map<String, Object> getProperties() {
Map<String, Object> properties = new HashMap<>();
// in Jersey WADL generation is enabled by default, but we don't
// want to expose too much information about our apis.
// therefore we want to disable wadl (http://localhost:8080/service/application.wadl should return http 404)
// see https://jersey.java.net/nonav/documentation/latest/user-guide.html#d0e9020 for details
properties.put("jersey.config.server.wadl.disableWadl", true);
// we could also use something like this instead of adding each of our resources
// explicitly in getClasses():
// properties.put("jersey.config.server.provider.packages", "com.nabisoft.tutorials.mavenstruts.service");
return properties;
}
}
That should make the deal and you should be able to call http://10.236.51.14:9000/abcd/api/add/1/2. ApplicationConfig is annotated with #Path("api"). That means all classes registered in this config have the root path http://your.server.address/api/.
Now to your problem. I assume your server is working and you can reach your Webservice /add/1/2 displaying the result 3 in your browser.
Now you need another service listening for a POST. I'd take your already prepared String as the posted body.
#Path("image")
public class ImageReceiverRestService {
#POST
public Response checkAssignable(String base64ImageString) {
// code here working with the base64ImageString
// response code according to whatever happened during your algorithm
return Response.ok().build();
}
}
For appropriate HTTP response codes see this Wikipedia article for a quick overview HTTP Status Codes
So now you'd need a corresponding client on your android app. For example:
public class ImageSendingRestClient {
private final static String SERVER_BASE_URI = "http://10.236.51.14:9000/abcd/api/";
private final static String API_ADDRESS = "image/";
public ImageSendingRestClient() {
}
#Override
public void sendImageStringForProcessing(String base64ImageString) throws Exception {
Entity<String> entity = Entity.json(base64ImageString);
Response response = ClientBuilder.newClient()
.target(SERVER_BASE_URI)
.path(API_ADDRESS)
.request()
.post(entity);
try {
if (response.getStatus() == Response.Status.OK.getStatusCode()) {
return;
}
if (response.getStatus() == Response.Status.NOT_FOUND.getStatusCode()) {
throw new Exception;
}
} finally {
response.close();
}
}
}
All dependencies needed are JAX-RS implementations like JAX-RS reference implementation Jersey. Maybe you should also check the Jersey Guide with many examples providing most of the information you need Jersey User Guide

Spring MVC - "IllegalArgumentException: Object reference not set to an instance of an object" when get SOAP response

I'm beginner in Spring MVC. I want to get response from SOAP web service. But i get a error message.
Here is my source code.
private static final String GET_DOCUMENT_SOAP_ACTION = "apvx:bus:ReportGenerator:{1D81BEDF-3894-45b2-99C9-95E50B1B9494}/Document_Get";
#Autowired
protected PathCentralWSTemplateFactory webServiceTemplateFactory;
public DocumentGetResponse documentGet(DocumentGet request) {
try {
return (DocumentGetResponse) webServiceTemplateFactory.getClient().marshalSendAndReceive(request,
getCallback(GET_DOCUMENT_SOAP_ACTION));
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
PathCentralWSTemplateFactoryImpl
public PathCentralWSTemplateFactoryImpl() throws SOAPException {
marshaller = new Jaxb2Marshaller();
messageFactory = new SaajSoapMessageFactory();
MessageFactory obj = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
if(obj != null){
((SaajSoapMessageFactory) messageFactory).setMessageFactory(obj);
}
((SaajSoapMessageFactory) messageFactory).setSoapVersion(org.springframework.ws.soap.SoapVersion.SOAP_11);
url = "https://www.mypathcentral.net/...";
}
#Override
public WebServiceTemplate getClient() {
WebServiceTemplate webServiceTemplate = new WebServiceTemplate(messageFactory);
webServiceTemplate.setMarshaller(marshaller);
webServiceTemplate.setUnmarshaller((Unmarshaller) marshaller);
webServiceTemplate.setDefaultUri(url);
webServiceTemplate.setMessageSender(getMessageSender());
return webServiceTemplate;
}
I'm not familiar with the framework you have going on here but I have an idea as to what's wrong with your code. You are getting a message that says no object reference. I believe this is because you are declaring GET_DOCUMENT_SOAP_ACTION as a static final. The static keyword causes the system to allocate static memory outside of the heap separate from any object. I think if you declare the string as a standard object this might clear up that issue but I'm not sure if that would cause problems with the rest of your code.

Passing Java objects from JSP to an applet [duplicate]

I have an applet and I must send a request to a web application to get data from the server that is in a database. I am working with objects and it is very useful that the server responses me with objects!!
How an applet can communicate with a server?
I think web services method, RMI and... make me happy, but which is the best and reliable?
As long as its only your applet communicating with the server you can use a serialized object. You just need to maintain the same version of the object class in both the applet jar and on the server. Its not the most open or expandable way to go but it is quick as far as development time and pretty solid.
Here is an example.
Instantiate the connection to the servlet
URL servletURL = new URL("<URL To your Servlet>");
URLConnection servletConnect = servletURL.openConnection();
servletConnect.setDoOutput(true); // to allow us to write to the URL
servletConnect.setUseCaches(false); // Write the message to the servlet and not from the browser's cache
servletConnect.setRequestProperty("Content-Type","application/x-java-serialized-object");
Get the output stream and write your object
MyCustomObject myObject = new MyCustomObject()
ObjectOutputStream outputToServlet;
outputToServlet = new ObjectOutputStream(servletConnection.getOutputStream());
outputToServlet.writeObject(myObject);
outputToServlet.flush(); //Cleanup
outputToServlet.close();
Now read in the response
ObjectInputStream in = new ObjectInputStream(servletConnection.getInputStream());
MyRespObject myrespObj;
try
{
myrespObj= (MyRespObject) in.readObject();
} catch (ClassNotFoundException e1)
{
e1.printStackTrace();
}
in.close();
In your servlet
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
MyRespObject myrespObj= processSomething(request);
response.reset();
response.setHeader("Content-Type", "application/x-java-serialized-object");
ObjectOutputStream outputToApplet;
outputToApplet = new ObjectOutputStream(response.getOutputStream());
outputToApplet.writeObject(myrespObj);
outputToApplet.flush();
outputToApplet.close();
}
private MyRespObject processSomething(HttpServletRequest request)
{
ObjectInputStream inputFromApplet = new ObjectInputStream(request.getInputStream());
MyCustomObject myObject = (MyCustomObject) inputFromApplet.readObject();
//Do Something with the object you just passed
MyRespObject myrespObj= new MyRespObject();
return myrespObj;
}
Just remember that both Objects that you are passing need to implement serializable
public Class MyCustomObject implements java.io.Serializable
{

Categories