I have the following classes:
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="vehicletype", discriminatorType = DiscriminatorType.STRING)
public abstract class AbstractVehicle {
...
#Entity
#DiscriminatorValue(value = VehicleTypes.Values.Car)
public class Car extends AbstractVehicle {
...
#NoRepositoryBean
public interface AbstractVehicleRepository<T extends AbstractVehicle> extends PagingAndSortingRepository<T, Long> {
...
#RepositoryRestResource(collectionResourceRel="cars", path="cars")
public interface CarRepository extends AbstractVehicleRepository<Car> {
...
(discriminator values are constants within enums as described here)
Running against a MySQL database.
I can start my Spring Boot application, but when I try to access the REST URL /cars, I get an exception complaining that the abstract_vehicle table doesn't exist.
I'm using Spring Boot 1.3.1 on a MySQL database, with the Spring Starts for Security, Web, Data-Rest, Hal-Browser and Data-Jpa in my dependencies.
Is SINGLE_TABLE inheritance compatible with Spring Data Rest Repositories? What am I doing wrong?
Related
I am creating the admin page for mobile recharge website using spring boot and SQL for backend. I have created separate tables for storing plans of prepaid, postpaid and add-ons. Now I would like to integrate all the three tables.
That is, when I enter (/prepaid) URL it should show the data of prepaid table, when I enter (/postpaid) URL it should show the data of postpaid table and like the same for add-ons. I don't have any idea about integration. Can anyone share some example or give some idea about it
Github link for code. This the spring boot code for prepaid. Like the same I have done for postpaid and add-on. Kindly refer the code and share your ideas
It will also work the same way as u are handling your Admin.
Note: Basically u need Model for every table and repository for each Model.
Model
#Table(name = "prepaid")
public class Prepaid implements Serializable{
/*all fields here*/
/*Getter and Setter*/
}
#Table(name = "postpaid")
public class Postpaid implements Serializable{
/*all fields here*/
/*Getter and Setter*/
}
#Table(name = "addon") //<--necessary in all model
public class Addons implements Serializable{
/*all fields here*/
/*Getter and Setter*/
}
Repository
public interface PrepaidRepo extends JpaRepository<Prepaid,Long> {
/*all functions here*/
}
public interface PostpaidRepo extends JpaRepository<Postpaid,Long> {
/*all functions here*/
}
public interface AddonRepo extends JpaRepository<Addon,Long> {
/*all functions here*/
}
Service
public class PostpaidService{
PostpaidRepo postpaid;
/*handling functions*/
}
public class PrepaidService{
PrepaidRepo prepaid;
/*handling functions*/
}
public class AddonService{
AddonRepo addon;
/*handling functions*/
}
Controller
#RequestMapping("/prepaid-plan")
public class PrepaidController{
/*route handling functions*/
}
#RequestMapping("/postpaid-plan")
public class PostpaidController{
/*route handling functions*/
}
#RequestMapping("/addon-plan")
public class AddonController{
/*route handling functions*/
}
I currently use SpringBoot1.5 and Junit5.
How do I use #autowire to dependency injection when I use the annotation #ParameterizedTest for parametric testing because I need to interact with the database.
I try to use
TestContextManager testContextManager = new TestContextManager(getClass());
testContextManager.prepareTestInstance(this);
but it will cause the #transaction to be unavailable.
this my code
#ExtendWith(MockitoExtension.class)
#RunWith(SpringRunner.class)
public abstract class AbstractUnitTest {
}
public class PatientFacadeTestParameterized extends AbstractUnitTest {
...
#Autowired
PatientFacade patientFacade;(is null)
...
#Transactional
#ParameterizedTest(name = "{index}: {0}")
#YamlFileSource(resources = {"logistics/patient_facade.yaml"})
public void testCreateAccountPhonePatienta(PatientFacadeData patientFacadeData) {
...
patientFacade.createAccountPhonePatient(patientForm1);
...
}
...
I just want to use #ParameterizedTest to manage my input.
Spring Boot 1.5.x depends on Spring Framework 4.3.x, but the latter does not provide built in support for JUnit Jupiter (a.k.a., JUnit 5).
So, if you want to use Spring Framework 4.3.x with JUnit Jupiter, the only option is to use my spring-test-junit5 project.
Once you have configured the dependency on spring-test-junit5, you will have access to the SpringExtension for JUnit Jupiter. This replaces the SpringRunner for JUnit 4.
You should then be able to rewrite your test class in a manner similar to the following. I cannot provide you an exact working example, since I do not have access to the types in your project.
#ExtendWith(SpringExtension.class)
#ExtendWith(MockitoExtension.class)
public class PatientFacadeTestParameterized {
#Autowired
PatientFacade patientFacade;
#Transactional
#ParameterizedTest(name = "{index}: {0}")
#YamlFileSource(resources = {"logistics/patient_facade.yaml"})
public void testCreateAccountPhonePatienta(PatientFacadeData patientFacadeData) {
// ...
patientFacade.createAccountPhonePatient(patientForm1);
// ...
}
What is responsible for injecting the PatientFacadeData into your test method? Does #YamlFileSource take care of that?
By the way, you should practically never need to use the TestContextManager directly in your tests. The SpringRunner and SpringExtension handle that for you.
On an Asp.Net Core project I am injecting Entity Framework DbContext:
public MessageRepository(MyDbContext context) {
}
And the configuration is:
services
.AddEntityFramework()
.AddSqlServer()
.AddDbContext<Context>(x => x.UseSqlServer(connectionString);
Should I create an interface, IMyDbContext, and injecting it instead?
public class MyDbContext : DbContext, IMyDbContext { }
public MessageRepository(IMyDbContext context) {
}
In all ASP.NET Core examples I see the concrete type, MyDbContext, is being injected and not an interface ...
What option should I choose?
Currently working on a project myself, where I decided to go with 2 interfaces like this
public interface IDbContext : IDisposable
{
DbContext Instance { get; }
}
and
public interface IApplicationDbContext : IDbContext
{
DbSet<MyEntity> MyEntities { get; set; }
...
}
My concrete DbContext would then just implement the application context interface
public class ApplicationDbContext : DbContext, IApplicationDbContext
{
public DbContext Instance => this
public DbSet<MyEntity> MyEntities { get; set; }
}
This allows my implementation of the Application context to be injected as the application context interface, while also providing me access to the DbContext methods through the Instance property getter without having to add methods needed from the DbContext class to the interface.
Until now, this works great.
We're always injecting an interface, since it's easier to mock in unit and integration tests.
Are you willing to change the signature of the MessageRepository constructor? It relies on the concrete type.
Do you write tests for your code? Using and interface would make it easier to mock the database context.
If you've answered "no" to one or more of the above, inject the concrete type; otherwise, inject the interface.
[EDIT]
use the following.
context services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());
In my opinion, you should always rely on an interface as #Uli said, but when it comes to the DbContext you need to take in mind that you are exposing all methods of the DbContext of EntityFramework Core
public class MyDbContext : DbContext, IMyDbContext { }
in that case, you don't need to implement any method that you are exposing because DbContext handles that for you.
BUT if EF code change the DbContext and you make an update to your project then you will be on a painful situation of updating your IMyDbContext every time, also all your unit testing. In my opinion, that will give you a lot of headaches.
This answers/questions can help you to understand why https://stackoverflow.com/a/6768712/819153
Unit testing EF - how to extract EF code out from BL?
According COMPOSITION ROOT pattern, I must to construct all dependencies graph as close as possible to the application's entry point.
My architecture is plugin oriented. So, if someone wants to extend my base system he can.
For example, in my base system I have this structure:
View Layer
Services Layer
Data Access Layer
Model Layer
In DAL, I expose some classes like:
IRepository
NHibernateRepository
ProductRepository
So, I'd like if a plugin wants to extend my base Product class to ExtendedProduct, and then create ExtendedProductRepository that inherits from NHibernateRepository.
The question is:
How can instantiate from my base system an instance of NHibernateRepository using NInject?
So, I know the first thing to do is to construct the graph dependencies:
using (var kernel = new StandardKernel())
{
kernel.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom<IRepository>()
.BindAllInterfaces());
}
However, I'm figuring out that when I execute something like:
kernel.GetAll<IRepository>()
It's going to return me a ProductRepository instance, and another ProductExtendedRepository under two IRepository objects.
So, how I can save a ProductExtended object from my base system...?
Another question, would be, how could I inject a object instance in my plugins, or, how can plugins autoinject some instance of base system assembly?
Thanks for all.
I'll appreciate a lot some help.
I use this pattern for my NHibernate based projects:
public interface IRepository<T> : IQueryable<T>
{
T Get(int id);
void Save(T item);
void Delete(T item);
}
public class NHibernateRepository<ModelType> : IRepository<ModelType>
where ModelType : class
{
// implementation
}
then...
public interface IProductRepository : IRepository<Product>
{
// product specific data access methods
}
public class ProductRepository : NHibernateRepository<Product>, IProductRepository
{
// implementation
}
... and in Ninject Module:
Bind(typeof(IRepository<>)).To(typeof(NHibernateRepository<>));
Bind<IProductRepository>().To<ProductRepository>();
then you can either request the base functionality like:
public Constructor(IRepository<Product> repo) { ... }
or specific product repository functionality:
public Constructor(IProductRepository repo) { ... }
your plugins can either get the base functionality and won't have to register anything:
public PluginConstructor(IRepository<ProductExtended> repo { ... }
or create their own repositories and register them in a Ninject module.
Thanks dave.
It's perfect. I'll try it.
However, how could I save or get or update (whichever IRepository methods)... an ExtendedProduct instance from my base system?
Think the follow out:
public interface BasePlugin<T> {...}
In another assembly:
public class PluginExtendedProduct : BasePlugin<ExtendedProduct>
{
public PluginExtendedProduct (IRepository<ExtendedProduct> repo { ... }
}
My headache is how to create an instance of (so, ExtendedProduct) in my base system in order to call methods PluginExtendedProduct that uses an IRepository.
I don't know if I'm explaining myself well...
Thanks for all.
I have a working project based on the Spring Data REST example project, and I'm trying to do custom serialization using a Jackson module based on this wiki page.
Here's my Jackson module:
public class CustomModule extends SimpleModule {
public static Logger logger = LoggerFactory.getLogger(CustomModule.class);
public CustomModule() {
super("CustomModule", new Version(1, 0, 0, null));
}
#Override
public void setupModule(SetupContext context) {
logger.debug("CustomModule.setupModule");
SimpleSerializers simpleSerializers = new SimpleSerializers();
simpleSerializers.addSerializer(new CustomDateTimeSerializer());
context.addSerializers(simpleSerializers);
}
}
The wiki page says:
Any Module bean declared within the scope of your ApplicationContext will be picked up by the exporter and registered with its ObjectMapper.
I'm still pretty new to Spring, so I might just be putting my module bean definition in the wrong place; currently it's in src/main/resources/META-INF/spring-data-rest/shared.xml, which is imported from repositories-export.xml:
<bean id="customModule" class="org.hierax.wpa.schema.mapping.CustomModule" />
I don't see the log statement in setupModule, but I do see log output for other classes in the same package.
I'm using Spring Data REST 1.0.0.RC2.
Currently, it's possible to customize a module in Spring Boot like this:
#Bean
public Module customModule() {
return new CustomModule();
}
Reference: Latest Jackson integration improvements in Spring
I've had success using the solution outlined in the wiki entry that you have linked to (although perhaps it has changed since this stack overflow post)
In my instance I was using spring-data-rest-webmvc#1.0.0.RELEASE
Your code seems to be correct and provided that your application context is being loaded correctly I don't see any reason for it not to be working.
I've attached my simpler Module which exemplifies the use of a date formatter:
#Component
public class JsonMarshallingConfigModule extends SimpleModule {
public JsonMarshallingConfigModule() {
super("JsonMarshallingConfigModule", new Version(1, 0, 0, "SNAPSHOT"));
}
#Override public void setupModule(SetupContext context) {
context.getSerializationConfig().setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'"));
}
}
Perhaps it can be used to outline if it is infact the jackson module that is the problem or spring-data-rest-mvcweb.