How to add new sub resource to a standard Intershop AbstractResourceObject - intershop

I want to introduce a new sub resource to standard Intershop ProductResource
without loosing the product resource context.
E.g In my resource's code, I want to know about the product to which a REST client is referring to /product/SOME/my-sub-resource
How can I do this ?

There is a recipe in "Cookbook - REST Framework":
Add a Resource to an Existing REST API
https://support.intershop.com/kb/index.php/Display/28269L

You need to add a new java class extending com.intershop.component.rest.capi.resource.AbstractRestResource
Register the implementation in a component file
<implementation name="YOUR_NAME"
implements="AbstractRestResource"
class="YOUR_FQNAME_TO_IMPL_CLASS"
factory="JavaBeanFactory">
<requires name="name" contract="String" cardinality="1..1" />
<requires name="subResource" contract="RestResource" cardinality="0..n" />
</implementation>
Instantiate the implementation in a component file
<instance with="YOUR_NAME" name="YOUR_INSTANCE_NAME">
<fulfill requirement="name" value="YOUR_SUBRESOUCE_NAME" />
</instance>
Add as subResource to intershop.WebShop.RESTAPI.ProductResource instance
<fulfill requirement="subResource"
of="intershop.WebShop.RESTAPI.ProductResource"
with="YOUR_INSTANCE_NAME"/>
After that your resource is available under /product/SKU/YOUR_SUBRESOURCE_NAME. Make sure your impl class has a public method and that method is annotated with javax.ws.rs.GET and javax.ws.rs.Produces
#GET
#Produces("application/json")
public SomeRO get()
{
ApplicationBO applicationBO = provider.get();
ProductBORepository productBORep = applicationBO.getRepository(ProductBORepositoryExtension.EXTENSION_ID);
ProductBO product = productBORep.getProductBOBySKU(getParent().getName());
// Do the stuff you want with the product
}

Related

Spring Data Rest: Entity serialization with LAZY object cause JsonMappingException

I'm getting the following Exception with a Spring Data Rest project:
com.fasterxml.jackson.databind.JsonMappingException:
No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer
(to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) )
(through reference chain: org.springframework.data.rest.webmvc.json.["content"]->test.spring.data.rest.xml.entities.Author_$$_jvstb93_1["handler"])
Certainly, I have some entities that have the fetch configuration = FetchType.LAZY.
I followed many instructions and links, but I still have this exception.
What I have already tried to do (with NO effetcs):
add #EnableHypermediaSupport(type = HypermediaType.HAL) in a config class that extends RepositoryRestMvcConfiguration
#Override configureJacksonObjectMapper in the same class, with also using Jackson2DatatypeHelper.configureObjectMapper():
#Override
protected void configureJacksonObjectMapper(ObjectMapper objectMapper) {
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
Jackson2DatatypeHelper.configureObjectMapper(objectMapper);
}
add a "org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter" filter in the web.xml
create a custom class that extends ObjectMapper, with this constructor:
public HibernateAwareObjectMapper() {
Hibernate5Module hm = new Hibernate5Module();
registerModule(hm);
}
and this config:
<mvc:annotation-driven>
<mvc:message-converters>
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="test.spring.data.rest.xml.config.HibernateAwareObjectMapper" />
</property>
</bean>
</mvc:message-converters>
No one of the actions above has solved the problem!
How to (definitely) solve this problem?
Thanks.
I have found the solution to this annoying problem.
For every repository of the Spring Data Rest application it has to be defined a custom #Projection; in the projection there will be the necessaries fields.
Pay attention that if there are cycylc references between two entities, the corrispective methods of the projections have to be annotated with #JsonBackReference annotation (for #ManyToOne annotated fields) and with #JsonManagedReference annotation (for #OneToMany annotated fields), otherwise there will be a JSON loop in the JSON serialization.
In every #Repository annotation (or #RepositoryRestResource annotation) it has to be marked the excerptProjection property, with the custom projection.
With this management, there is no need of any other configuration, and the exception for Lazy objects finally is vanished.

creating and access properties file in spring mvc

read this article on SO, and had some clarifying questions.
I put my config.properties under src/main/resources
In spring-servlet.xml config file
I added the following:
<context:property-placeholder location="classpath:config.properties"/>
In my business layer, I am trying to access it via
#Value("${upload.file.path}")
private String uploadFilePath;
Eclipse shows error:
The attribute value is undefined for the annotation type Value
Can i not access the property in the business layer or are property files only read in the controller?
UPDATE::
src/main/java/com.companyname.controllers/homecontroller.java
public String home(Locale locale, Model model) {
MyServiceObject myObj = new MyServiceObject();
System.out.println("Property from my service object: = " + myObj.PropertyValue());
if(myObj.PerformService())
{
///
}
}
src/main/java/com.companyname.services/MyService.java
public class MyServiceObject {
#Value("${db.server.ip}")
private String _dbServerIP;
public String PropertyValue() {
return _dbServerIPaseURL;
}
}
Another site where I found the explanation
Please check that you import Value from org.springframework.beans.factory.annotation package:
import org.springframework.beans.factory.annotation.Value;
also the property placeholder must be declared in the respective context configuration file, in case of controller it's likely Spring dispatcher servlet configuration file.
update You are confusing property-placeholder that post processes bean values, that contain dollar symbol ${<property name>} with Spring expression language container extension that process values containing a hash symbol #{<Spring expression language expression>}, in the link you have shown the latter approach is used.
regarding the instantiation of MyServiceObject myObj
If you want the object to be managed by Spring you should delegate its creation to the container:
if MyServiceObject is a stateless service then it's a singleton with the singleton bean scope, you should register it in your application context, for example with the following xml configuration:
<bean class="my.package.MyServiceObject"/>
and inject it to your controller:
private MyServiceObject myServiceObject;
#Autowired
public void setMyServiceObject(MyServiceObject myServiceObject){
this.myServiceObject = myServiceObject;
}
if many instances of MyServiceObject are required, you can declare it as a bean with some other (non-singleton) bean scope (prototype, or request, for example).
However, as there's only one instance of the controller, you can't merely let the Spring container to autowire MyServiceObject instance to the controller field, because there will be only one field and many instances of MyServiceObject class. You can read about the different approaches(for the different bean scopes) for resolving this issue in the respective section of the documentation.
Here is a method that allows us to fetch whatever values are needed from a property file. This can be in Java code (Controller class) or in a JSP.
Create a property file WEB-INF/classes/messageSource.properties It will be in the classpath and accessible in both controllers and JSTL.
Like any property file, this one consists of a key and a value
For example:
hello=Hello JSTL, Hello Contoller
For the Controllers
Locate the xml file that you use to define your Spring beans. In my case it is named servlet-context.xml. You may need to determine that by looking in your web.xml in cases where you are using the servlet contextConfigLocation property.
Add a new Spring bean definition with the id="messageSource". This bean will be loaded at runtime by Spring with the property file key value pairs. Create the bean with the following properties:
bean id="messageSource"
class = org.springframework.context.support.ReloadableResourceBundleMessageSource
property name="basename" value="WEB-INF/classes/messageSource
In the bean definition file for the controller class (testController) add the messageSource as a property. This will inject the messageSource bean into the controller.
bean id="testController" class="com.app.springhr.TestController"
beans:property name="messageSource" ref="messageSource"
In the controller JAVA class, add the messageSource Spring Bean field and its getters and setters. Note the field type is ReloadableResourceBundleMessageSource.
private org.springframework.context.support.ReloadableResourceBundleMessageSource messageSource;
public org.springframework.context.support.ReloadableResourceBundleMessageSource getMessageSource() {
return messageSource;
}
public void setMessageSource(
org.springframework.context.support.ReloadableResourceBundleMessageSource messageSource) {
this.messageSource = messageSource;
}
In your controller code, you can now fetch any known property value from the bundle.
String propValue = getMessageSource().getMessage("hello", objArray, null);
Using JSTL
Since the property file messageSource.properties is in the classpath, JSTL will be able to find it and fetch the value for the given key.
Add the import of the fmt taglib
taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"
Use the fmt:tag in the JSP to fetch a value from the property file.
Sorry about the pseudo syntax, this editor doesn't seem to render any XML.
fmt:bundle basename="messageSource"
fmt:message key="hello"
Hope this helps others

Microsoft Unity - Is it possible to change the registered type at runtime?

I am currently using Unity with MOQ to do my unit testing for WCF. In the application's code, I have the following:
private void MyMethod()
{
.....
.....
_proxy = new UnityContainer().LoadConfiguration().Resolve<IMyInterface>();
.....
}
In the application's app.config, I have the following:
<container>
<register type="IMyInterface" mapTo="MyActualObject" />
</container>
In the unit test's app.config, I replace that with my mock object implementation of the proxy.
<container>
<register type="IMyInterface" mapTo="MyMockObject" />
</container>
That is all working fine. But what I would like to do further is for certain tests, I would like to replace MyMockObject with a different mock object implementation.
Is it possible to change the registered type at runtime? I have tried modifying the application config during runtime but it fails to detect the change.
Configuration appConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var section = (UnityConfigurationSection)appConfig.GetSection("unity");
section.Containers[0].Registrations[0].MapToName = "AnotherMockObject";
appConfig.Save();
Thanks!!
Yes its possible.
You can configure Unity as many times as you want. If there's a conflict the most recent definition wins.
In your case if you want to make a runtime change, use the fluent API instead of the config file. Try something like this:
IUnityContainer container = new UnityContainer();
container.LoadConfiguration();
container.RegisterType<IMyInterface, AnotherMockObject>();
// use AnotherMockObject
_proxy = Resolve<IMyInterface>();
The documentation for Registering Types and Type Mappings

Orchard/MVC WCF Service Url with Area

Bertrand created a blog post to specify how to use IoC in WCF Modules for Orchard.
In 1.1, you can create a SVC file using the new Orchard host factory:
<%# ServiceHost Language="C#" Debug="true"
Service="MyModule.IMyService, MyAssembly"
Factory="Orchard.Wcf.OrchardServiceHostFactory, Orchard.Framework" %>
Then register your service normally as an IDependency but with service and operation contract attributes:
using System.ServiceModel;
namespace MyModule {
[ServiceContract]
public interface IMyService : IDependency {
[OperationContract]
string GetUserEmail(string username);
}
}
My question is that all of Orchard's modules are really area's. So how can you build a route that hits the svc file created in the area/module?
Should you use the full physical path to get to the svc file (tried that and it caused a web.config issue since it was bridging a site and area).
http://localhost/modules/WebServices/MyService.svc
Or do you create a ServiceRoute with WebServiceHostFactory/OrchardServiceHostFactory?
new ServiceRoute("WebServices/MyService", new OrchardServiceHostFactory(), typeof(MyService))
Whatever I try I get a 404 when trying to hit the resource. I was able to get this working using a wcf Application project and setting WCF as a stand alone application, my issues started when trying to bring it into Orchard/MVC.
UPDATE
Thanks for the help Piotr,
This is the steps I took to implement the service.
Routes.cs
new RouteDescriptor { Priority = 20,
Route = new ServiceRoute(
"Services",
new WebServiceHostFactory(),
typeof(MyService)) }
If I use OrchardServiceHostFactory() instead of WebServiceHostFactory() I get the following error.
Operation is not valid due to the current state of the object.
Orchard Root Web.Config
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
<standardEndpoints>
<webHttpEndpoint>
<!--
Configure the WCF REST service base address via the global.asax.cs file and the default endpoint
via the attributes on the <standardEndpoint> element below
-->
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
MyService
[ServiceContract]
public interface IMyService : IDependency
{
[OperationContract]
string GetTest();
}
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
class MyService : IMyService
{
public string GetTest()
{
return "test";
}
}
I couldn't get the service working by just modifying the module's web.config. I get the following error
ASP.NET routing integration feature requires ASP.NET compatibility.
UPDATE 2
Orchard Root Web.Config
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<!-- ... -->
</system.serviceModel>
Routes.cs
public IEnumerable<RouteDescriptor> GetRoutes() {
return new[] {
new RouteDescriptor { Priority = 20,
Route = new ServiceRoute(
"Services",
new OrchardServiceHostFactory(),
typeof(IMyService))
}
};
}
This works, the key here is that you must call typeof on the object that is referencing IDependency, WorkContextModule.IsClosingTypeOf cant handle the object that consumes the dependancy, it must take the Interface that it is directly called by.
As you stated, Orchard modules are areas in ASP.NET MVC terms, so the URL you provided is incorrect and should be:
http://localhost/Your.Orchard.Module/WebServices/MyService.svc
Where localhost is the virtual directory under which your app runs and /WebServices is a folder in the root of your module.
You can also create a service route programatically without problem. This article tells how to add new routes in Orchard. You can just assign a ServiceRoute to the Route property of a RouteDescriptor instead of a default MVC route (as shown in docs).
The question about adding ServiceRoute in area-enabled ASP.NET MVC app was asked before, check it out as it may help you out.
Btw - You may also check this SO question about prefixed service routes.
HTH

OpenEJB : Configuring MDBs with custom ConnectionFactory

As described in OpenEJB docs, we can configure JMS connection factory and queues, and they will appear in JNDI as:
openejb:Resource/MyJmsConnectionFactory,
openejb:Resource/MyQueue
Given those JNDI entries, how can I tell to MDB to use them?
Is it possible to change JNDI name, for example ConnectionFactory to appear as java:/ConnectionFactory
or ConnectionFactory
Things work differently than you may be imagining. Specifying that an MDB is tied to a javax.jms.Queue and the name of that queue is part of the EJB specification and done via the ActivationConfig, like so:
#MessageDriven(activationConfig = {
#ActivationConfigProperty(
propertyName = "destinationType",
propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(
propertyName = "destination",
propertyValue = "FooQueue")})
public static class JmsBean implements MessageListener {
public void onMessage(Message message) {
}
}
The MDB container itself is not actually JMS-aware at all. It simply understands that it should hook the bean up to a specific Resource Adapter.
<openejb>
<Resource id="MyJmsResourceAdapter" type="ActiveMQResourceAdapter">
ServerUrl tcp://someHostName:61616
</Resource>
<Container id="MyJmsMdbContainer" ctype="MESSAGE">
ResourceAdapter MyJmsResourceAdapter
</Container>
</openejb>
The above shows an MDB Container hooked up to a Resource Adapter that uses JMS via ActiveMQ.
Here is an example that shows an MDB Container hooked up to a Quartz Resource Adapter
It isn't possible to tell the MDB Container about JMS specific things as per specification, the relationship is much more generic than that. This blog post gives some insight as to how things work.

Resources