I am trying to create a REST web-service in Java using RestEasy with the design similar to the example classes that I have shown below:
#Path("/rest")
public class TestRestService {
#GET
#Path("/test")
#Produces("application/xml")
public Response sayTestXml() {
return getImplementation();
}
public Response getImplementation() {
IInterface refToImpl = TestService.getImplementation();
return Response.status(Status.OK).entity(refToImpl).build();
}
}
public class TestService {
public static IInterface getImplementation() {
IInterface ref = new Implementation();
return ref;
}
}
public interface IInterface {
public long getLong();
public String getString();
public boolean getBoolean();
public List<IRelatedInterface> getRelations();
}
public interface IRelatedInterface {
public float getFloat();
public char getChar();
public byte getByte();
}
#XmlRootElement(name="interface")
#XmlAccessorType(XmlAccessType.PROPERTY)
public class Implementation implements IInterface {
#XmlElement(name="tlong", required=true)
public long getLong() {
return 42;
}
#XmlElement(name="tstring", required=true)
public String getString() {
return "test";
}
#XmlElement(name="tboolean", required=true)
public boolean getBoolean() {
return false;
}
#XmlElementWrapper(name = "relations")
#XmlElement(name = "relation", required=false)
public List<IRelatedInterface> getRelations() {
List<IRelatedInterface> list = new ArrayList<IRelatedInterface>();
RelatedImplementation impl = new RelatedImplementation();
list.add(impl);
return list;
}
}
#XmlRootElement(name="relatedInterface")
#XmlAccessorType(XmlAccessType.PROPERTY)
public class RelatedImplementation implements IRelatedInterface {
#XmlElement(name="tfloat", required=true)
public float getFloat() {
return 1.23f;
}
#XmlElement(name="tchar", required=true)
public char getChar() {
return 'A';
}
#XmlElement(name="tbyte", required=true)
public byte getByte() {
return 'Z';
}
}
So, when I try this design then JAXB complains as below:
com.sun.xml.bind.v2.runtime.IllegalAnnotationsException:
2 counts of IllegalAnnotationExceptions com.intuit.whitespace.IRelatedInterface is an interface, and JAXB can't handle interfaces.
this problem is related to the following location: at com.intuit.whitespace.IRelatedInterface at public java.util.List com.intuit.whitespace.Implementation.getRelations() at com.intuit.whitespace.Implementation com.intuit.whitespace.IRelatedInterface does not have a no-arg default constructor. this problem is related to the following location: at com.intuit.whitespace.IRelatedInterface at public java.util.List com.intuit.whitespace.Implementation.getRelations() at com.intuit.whitespace.Implementation
My question is, is there a way to solve this? I have tried some things but none of them have worked. I am considering Spring OXM or a MessageBodyWriter based solution, but I wanted to ask if there were any other suggestions that would help me better?
Okay, I solved it by making the following changes:
Used the type attribute in #XmlElement
public class Implementation implements IInterface {
#XmlElementWrapper(name = "relations")
#XmlElement(name = "relation", required=false, type=RelatedImplementation.class)
public List<IRelatedInterface> getRelations() {
....
}
}
That is all!
Related
I am trying to spy private method with PowerMock but on the line when I define the what should be returned when the private method is called, it calls the method and I am getting and Null Pointer Exception. What PowerMock is calling real method on this line ?
myService= PowerMockito.spy(new MyService(myParam));
.....
PowerMockito.when(myService, "getCLientBy", anyString(), anyString(), anyString()).thenRetur`n(Client.of(setName, new HashSet<>())); // here it calls real method
Ensure that you prepare your class to be used in spy by adding #PrepareForTest(MyService.class)
#RunWith(PowerMockRunner.class)
// We prepare MyService for test because it's final
// or we need to mock private or static methods
#PrepareForTest(MyService.class)
public class YourTestCase {
//...
#Test
public void spyingWithPowerMock() {
MyService classUnderTest = PowerMockito.spy(new MyService(myParam));
//.....
// use PowerMockito to set up your expectation
PowerMockito.doReturn(Client.of(setName, new HashSet<>()))
.when(classUnderTest, "getClientBy", anyString(), anyString(), anyString());
//...
Also make sure provide the correct method name to be invoked.
#user1474111 and #Nkosi
I've built a small simulation of your example.
Maybe you also need to add the Client class in the PrepareForTest annotation.
#RunWith(PowerMockRunner.class)
#PrepareForTest({ MyService.class, Client.class })
public class Example1Test {
#Test
public void testPowerMockito() throws Exception {
MyService myService = PowerMockito.spy(new MyService("myParam"));
PowerMockito.when(myService, "getClientBy", ArgumentMatchers.anyString(), ArgumentMatchers.anyString(),
ArgumentMatchers.anyString()).thenReturn(Client.of("setName", new HashSet<String>()));
myService.run();
Assert.assertEquals("setName", myService.getClient().getName());
}
}
public class MyService {
private Client client;
public MyService(String param) { }
private Client getClientBy(String a, String b, String c) {
return new Client(a + b + c);
}
public Client getClient() {
return this.client;
}
public void setClient(Client client) {
this.client = client;
}
public void run() {
setClient(getClientBy("A", "B", "C"));
}
}
public class Client {
private final String name;
public Client(String name) {
this.name = name;
}
public static Client of(String name, HashSet<String> hashSet) {
return new Client(name);
}
public String getName() {
return name;
}
}
Is it possible in DryIoc container to figure out whether some singleton has been instantiated?
For instance
var container = new Container();
container.Register<IApplicationContext, ApplicationContext>( Reuse.Singleton );
// var context = container.Resolve<IApplicationContext>();
if ( container.IsInstantiated<IApplicationContext>() ) // Apparently this does not compile
{
// ...
}
// OR
if ( container.IsInstantiated<ApplicationContext>() )
{
// ...
}
There is no way at the moment and no such feature planned. You may create an issue to request this.
But I am wandering why it is needed. Cause singleton provides a guarantee to be created only once, so you may not worry or check for double creation.
Is it for something else?
Update
OK, in DryIoc you may register a "decorator" to control and provide information about decoratee creation, here is more on decorators:
[TestFixture]
public class SO_IsInstantiatedViaDecorator
{
[Test]
public void Test()
{
var c = new Container();
c.Register<IService, X>(Reuse.Singleton);
c.Register<XProvider>(Reuse.Singleton);
c.Register<IService>(
Made.Of(_ => ServiceInfo.Of<XProvider>(), p => p.Create(Arg.Of<Func<IService>>())),
Reuse.Singleton,
Setup.Decorator);
c.Register<A>();
var x = c.Resolve<XProvider>();
Assert.IsFalse(x.IsCreated);
c.Resolve<A>();
Assert.IsTrue(x.IsCreated);
}
public interface IService { }
public class X : IService { }
public class A
{
public A(IService service) { }
}
public class XProvider
{
public bool IsCreated { get; private set; }
public IService Create(Func<IService> factory)
{
IsCreated = true;
return factory();
}
}
}
This example also illustrates how powerful is composition of DryIoc decorators and factory methods.
Having some issues getting my repository to retrieve information - keeps coming back null. Any Thoughts would be appreciated - new to this and teaching myself.
Repository:
public class CustomerRepository : ICustomerRepository
{
private masterContext context;
public CustomerRepository(masterContext context)
{
this.context = context;
}
public IEnumerable<Customer> GetCustomers()
{
return context.Customer.ToList();
}
public Customer GetCustomerById(int customerId)
{
var result = (from c in context.Customer where c.CustomerId == customerId select c).FirstOrDefault();
return result;
}
public void Save()
{
context.SaveChanges();
}
Controller:
public class CustomerController : Controller
{
private readonly ICustomerRepository _repository = null;
public ActionResult Index()
{
var model = (List<Customer>)_repository.GetCustomers();
return View(model);
}
public ActionResult New()
{
return View();
}
}
MasterContext which i had efc make:
public partial class masterContext : DbContext
{
public masterContext(DbContextOptions<masterContext> options)
: base(options)
{ }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>(entity =>
{
entity.Property(e => e.CustomerName).IsRequired();
});
}
public virtual DbSet<Customer> Customer { get; set; }
public virtual DbSet<Order> Order { get; set; }
}
I think you need to create instances of you Context and your Repository. So in your Controller you need to something like this:
private masterContext context = new masterContext();
private ICustomerRepository repository = new CustomerRepository(context);
I assume that you're not using Dependency injection ... if so you just need to create a Constructor for your Controller that takes CustomerRepository as argument:
public CustomerController(ICustomerRepository _repository) {
repository = _repository;
}
If you did not configure your database context, look here: https://docs.efproject.net/en/latest/platforms/aspnetcore/new-db.html
This will than enable you the dependency injection. Everything you than need to do for the Repository is to use
services.AddScoped<ICustomerRepository,
CustomerRepository>();
And I think it could be good to remove the ToList() in the Repository class and remove the Cast List<Customer> in your Controller and use ToList() instead, if it's really needed. Because if you're using it in the View the ienumerable could also work.
I have two POJOs
#XmlRootElement
public class PojoBase {
}
#XmlRootElement
public class PojoRequest extends PojoBase {
private String strTemplate;
public void setTemplate(String strTemplate) {
this.strTemplate = strTemplate;
}
public String getTemplate() {
return strTemplate;
}
}
#XmlRootElement
public class PojoResponse extends PojoBase {
private String strName;
public void setName(String strName) {
this.strName = strName;
}
public String getName() {
return strName;
}
}
I have service which accepts the base class and returns the base class as response.
#POST
#Path("/start")
#Produces({MediaType.APPLICATION_JSON})
#Consumes(MediaType.APPLICATION_JSON)
public PojoBase registerNumber(JAXBElement<PojoBase> theRequest) {
//does some work with theRequest.
//here the theRequest object doesn't has pojoRequest data.
PojoResponse pojoResponse = new PojoResponse();
pojoResponse.setName("Sample");
return pojoResponse;
}
From client I am sending pojo base object but not sure why Restful doesn't get actual theRequest object.
Here is the client code:
public class HttpClient {
static String _strServiceURL = "http://127.0.0.1:8080/middleware/rest/service/start";
public static void main(String[] args) throws Exception {
PojoRequest pojoRequest = new PojoRequest();
pojoRequest.setTemplate("Somedata");
PojoBase response = getResponse(pojoRequest);
PojoResponse pojoresponse = (PojoResponse) response;
System.out.println(response);
}
private static PojoBase getResponse(PojoBase request) {
try {
Client client = Client.create();
WebResource webResource = client.resource(_strServiceURL);
ClientResponse response = webResource.type(javax.ws.rs.core.MediaType.APPLICATION_JSON).post(ClientResponse.class, request);
System.out.println(response.getStatus());
if(response.getStatus() == 200){
PojoBase response = response.getEntity(PojoBase.class);
return response;
}
} catch(Exception e) {
System.out.println(e.getMessage());
}
return null;
}
}
Can you please tell me how to get the PojoRequest at Service end?
Any help is appreciated.
Thanks
I don't think you can pass a superclass to jersey like this. I believe, though I may be wrong, that as registerNumber() has a parameter JAXBElement<PojoBase> it will do something like:
instantiate a PojoBase
do reflection on PojoBase (which has no properties), therefore nothing to set.
call registerNumber() with the practically empty PojoBase object
So why not try changing the signature to:
public PojoBase registerNumber(JAXBElement< PojoRequest > theRequest)
or even (with com.sun.jersey.api.json.POJOMappingFeature = true):
public PojoBase registerNumber(PojoRequest theRequest)
I designing an applications which basically has 3 different logic layers:
DB connector (implemented by ADO.NET).
BL the business logic (the only thing the UI knows).
DB repositories (connects between the first two).
The DB repositories are separated into sections of dependency and every final entity is polymorphic to one interface. In some cases there are dependencies between objects inside the same dependency sections - ISectionFactory (hence dependent).
In practice the BL is going to ask for an object of specific type (such as IngrediantType in my example) from the MainFactory (which is a factor for all the DB)
Because of this design I am forced to cast types on the UI - which obviously is a drag.
How can I change the design ?
Here is a brief look of design:
public class MainFactory
{
private Dictionary<Type, ISectionFactory> m_SectionsFactories;
private ISectionFactory treatmentsSectionFactory =
new TreatmentsSectionFactory();
public MainFactory()
{
m_SectionsFactories = new Dictionary<Type, ISectionFactory>
{
{typeof(IngrediantType),treatmentsSectionFactory}
};
}
public IConcreteDataCollection GetConcreteData(Type i_EntitiesName)
{
return m_SectionsFactories[i_EntitiesName]
.GetConcreteData(i_EntitiesName);
}
}
internal interface ISectionFactory
{
IConcreteDataCollection GetConcreteData(Type i_EntitiesName);
}
public class TreatmentsSectionFactory : ISectionFactory
{
private Dictionary<Type, IConcreteDataCollection>
m_ConcreteDataCollections;
private IngrediantTypes m_IngrediantTypes = new IngrediantTypes();
private Ingrediants m_Ingrediants = new Ingrediants();
public TreatmentsSectionFactory()
{
m_ConcreteDataCollections =
new Dictionary<Type, IConcreteDataCollection>();
m_ConcreteDataCollections
.Add(typeof(IngrediantType), m_IngrediantTypes);
m_ConcreteDataCollections
.Add(typeof(Ingrediants), m_Ingrediants);
}
public IConcreteDataCollection GetConcreteData(Type i_EntitiesName)
{
return m_ConcreteDataCollections[i_EntitiesName];
}
}
public interface IConcreteDataCollection : IEnumerable
{
// Iteratable.
IConcreteData GetById(int i_Id);
void AddNewConcreteData(IConcreteData i_ConcreteData);
void UppdateConcreteData(IConcreteData i_ConcreteData);
void DeleteConcreteData(IConcreteData i_ConcreteToDelete);
}
public class IngrediantTypes : IConcreteDataCollection
{
public string TestType { get; set; }
public IConcreteData GetById(int i_Id){}
public void AddNewConcreteData(IConcreteData i_ConcreteData){}
public void UppdateConcreteData(IConcreteData i_ConcreteData){}
public void DeleteConcreteData(IConcreteData i_ConcreteToDelete){}
public IEnumerator GetEnumerator(){}
}
// also implements IConcreteDataCollection
public class Ingrediants : IConcreteDataCollection
{
}
public interface IConcreteData
{
public int Index { set; get; }
} // the final (highest) entity of all DB entities
public class IngrediantType : IConcreteData
{
public int Index { set; get; }
// other set of properties
}
public class Ingrediant : IConcreteData
{
public int Index { set; get; }
public IngrediantType RelatedIngrediantType { set; get; }
// other set of properties
}
public class mainClass
{
public static void main()
{
MainFactory factory = new MainFactory();
var type = typeof(IngrediantType);
// returns a IngrdiantTypes of type (IConcreteDataCollection)
var t = factory.GetConcreteData(typeof(IngrediantType));
// I want to use the IngrediantType without casting !!!
var s = t.GetById(2);
}
}
It's a little hard to tell what's going on here, but I think the key will be to take advantage of generics like so:
public IConcreteDataCollection<T> GetConcreteData<T>()
{
return ...;
}
If I understand your question correctly, this will allow you to say:
var t = factory.GetConcreteData<IngrediantType>();
You will need to change almost every class in your code to use generics.